XOP (від англ. eXtended Operations – розширені операції [1]) – розширення набору інструкцій x86/AMD64, анонсоване корпорацією AMD 1 травня 2009 року.
Є розширенням та розвитком ідей, реалізованих у 128-бітих інструкціях SSE в архітектурах x86/x86-64. Реалізовано з мікроархітектури мікропроцесорів AMD Bulldozer (12 жовтня 2011).[2] Не підтримується процесорами AMD, починаючи з мікроархітектури Zen (Ryzen, EPIC; 2017 рік)[3].
У набір інструкцій XOP входить кілька різних типів векторних інструкцій, оскільки він був спочатку задуманий як велике оновлення SSE. Більшість інструкцій є цілими, але в набір також входять інструкції для перестановки чисел з рухомої комою та інструкції екстракції дробової частини.
XOP є переробкою частини ідей, призначених для SSE5. Набір було змінено, щоб зробити його більш схожим на AVX, але не дублювати інструкції. Інструкції, що збігаються з AVX, були видалені або переміщені в окремі розширення, наприклад FMA4 (векторне множення-додавання для рухомої коми) і CVT16 (перетворення чисел половинної-точності, реалізовано корпорацією Intel як F16C).[1]
Усі інструкції SSE5, для яких був аналог або еквівалент у наборах AVX та FMA3, використовують кодування, запропоновані корпорацією Intel. Цілочисленні інструкції без еквівалентів AVX були класифіковані як розширення XOP.[1] Інструкції XOP кодуються кодами операцій, що починаються з байта 0x8F (шістнадцяткове значення), але в іншому використовують схему кодування, майже ідентичну AVX з 3-байтовим префіксом VEX.
Окремі експерти (Agner Fog)[4] розцінили це як ознака того, що корпорація Intel не дозволила AMD використовувати будь-яку частину великого кодового простору VEX. Компанія AMD, ймовірно, була змушена використовувати відмінні коди для того, щоб уникнути будь-якої комбінації, яку міг би в майбутньому використовувати Intel. Схема кодування XOP максимально наближена до VEX, але усуває ризик перетину майбутніх опкодів Intel.
Використання байта 8F вимагає, щоб m-біт (див. схема кодування VEX) мав значення більше або дорівнює 8, щоб уникнути перетину з інструкціями, визначеними на даний момент. Байт 0xC4, який використовується у схемі VEX не має такого обмеження. Через це використання m-бітів для інших цілей у майбутньому в XOP схемі може бути утруднено (VEX не має обмежень на m-біти). Інша можлива проблема полягає в тому, що біти pp в XOP завжди мають значення 00, у той час як у VEX вони встановлюються значення 01 для вказівки, що в інструкції немає застарілих еквівалентів. Це може ускладнити використання pp бітів для інших цілей у майбутньому.
Аналогічна проблема сумісності - відмінності реалізацій розширень FMA3 та FMA4. Intel спочатку запропонував розширення FMA4 в рамках специфікації AVX/FMA версії 3, щоб замінити 3-операнди варіант FMA, запропонований AMD в SSE5. Після того як AMD реалізувала FMA4, Intel відмовився від FMA4 і повернувся до FMA3 у 5 версії специфікації AVX/FMA.[1][5][6]
У березні 2015 року компанія AMD розкрила в описі патча для пакету GNU Binutils що Zen, третє покоління архітектури x86-64, у першій редакції (znver1 — Zen, версія 1), не підтримуватиме TBM, FMA4, XOP and LWP інструкції, розроблені спеціально для сімейства мікроархітектури «Bulldozer».[7][8]
Ці інструкції є цілим аналогом наборів інструкцій FMA. Всі вони — чотириоперадні інструкції, схожі на FMA4, і всі вони працюють над знаковими цілими числами.
Інструкція | Опис[9] | Операція |
---|---|---|
VPMACSWW
|
Multiply Accumulate (with Saturation) Word to Word | 2x8 words (a0-a7, b0-b7) + 8 words (c0-c7) → 4 words (r0-r7)
r0 = a0 * b0 + c0, r1 = a1 * b1 + c1, .. |
VPMACSWD
|
Multiply Accumulate (with Saturation) Low Word to Doubleword | 2x8 words (a0-a7, b0-b7) + 4 doublewords (c0-c3) → 4 doublewords (r0-r3)
r0 = a0 * b0 + c0, r1 = a2 * b2 + c1, .[2] |
VPMACSDD
|
Multiply Accumulate (with Saturation) Doubleword to Doubleword | 2x4 doublewords (a0-a3, b0-b3) + 4 doublewords (c0-c3) → 4 doublewords (r0-r3)
r0 = a0 * b0 + c0, r1 = a1 * b1 + c1, .. |
VPMACSDQL
|
Multiply Accumulate (with Saturation) Low Doubleword to Quadword | 2x4 doublewords (a0-a3, b0-b3) + 2 quadwords (c0-c1) → 2 quadwords (r0-r3)
r0 = a0 * b0 + c0, r1 = a2 * b2 + c1 |
VPMACSDQH
|
Multiply Accumulate (with Saturation) High Doubleword to Quadword | 2x4 doublewords (a0-a3, b0-b3) + 2 quadwords (c0-c1) → 2 quadwords (r0-r3)
r0 = a1 * b1 + c0, r1 = a3 * b3 + c1 |
VPMADCSWD
|
Multiply Add Accumulate (with Saturation) Word to Doubleword | 2x8 words (a0-a7, b0-b7) + 4 doublewords (c0-c3) → 4 doublewords (r0-r3)
r0 = a0 * b0 + a1 * b1 + c0, r1 = a2 * b2 + a3 * b3 + c1, .. |
Інструкції горизонтального додавання додають суміжні значення у вхідному векторі одне до одного. Вихідний розмір у наведених нижче інструкціях описує ширину виконаного горизонтального додавання. Наприклад, горизонтальний «байт у слова» додає по два байти за раз і повертає результат у вигляді вектора слів, але «байт у четверне слово» додає вісім байтів разом і повертає результат у вигляді вектора чотирьох слів. Шість додаткових горизонтальних інструкцій додавання та віднімання можна знайти в SSSE3, але вони працюють з двома вхідними векторами і виконують лише дві операції.
Інструкція | Опис[9] | Операція |
---|---|---|
VPHADDBW
|
Horizontal add two signed/unsigned bytes to word | 16 bytes (a0-a15) → 8 words (r0-r7)
r0 = a0+a1, r1 = a2+a3, r2 = a4+a5, … |
VPHADDBD
|
Horizontal add four signed/unsigned bytes to doubleword | 16 bytes (a0-a15) → 4 doublewords (r0-r3)
r0 = a0+a1+a2+a3, r1 = a4+a5+a6+a7, … |
VPHADDBQ
|
Horizontal add eight signed/unsigned bytes to quadword | 16 bytes (a0-a15) → 2 quadwords (r0-r1)
r0 = a0+a1+a2+a3+a4+a5+a6+a7, … |
VPHADDWD
|
Horizontal add two signed/unsigned words to doubleword | 8 words (a0-a7) → 4 doublewords (r0-r3)
r0 = a0+a1, r1 = a2+a3, r2 = a4+a5, … |
VPHADDWQ
|
Horizontal add four signed/unsigned words to quadword | 8 words (a0-a7) → 2 quadwords (r0-r1)
r0 = a0+a1+a2+a3, r1 = a4+a5+a6+a7 |
VPHADDDQ
|
Horizontal add two signed/unsigned doublewords to quadword | 4 doublewords (a0-a3) → 2 quadwords (r0-r1)
r0 = a0+a1, r1 = a2+a3 |
VPHSUBBW
|
Horizontal subtract two signed bytes to word | 16 bytes (a0-a15) → 8 words (r0-r7)
r0 = a0-a1, r1 = a2-a3, r2 = a4-a5, … |
VPHSUBWD
|
Horizontal subtract two signed words to doubleword | 8 words (a0-a7) → 4 doublewords (r0-r3)
r0 = a0-a1, r1 = a2-a3, r2 = a4-a5, … |
VPHSUBDQ
|
Horizontal subtract two signed doublewords to quadword | 4 doublewords (a0-a3) → 2 quadwords (r0-r1)
r0 = a0-a1, r1 = a2-a3 |
Цей набір векторних інструкцій використовує поле immediate кодування як додатковий аргумент, який визначає яке саме порівняння виконувати. Існує вісім можливих варіантів порівняння для кожної інструкції. Вектори порівнюються і всі порівняння, що виявилися істинними, встановлюють всі біти у відповідному регістрі призначення в 1, а помилкові порівняння - встановлюють біти в 0. Цей результат може бути безпосередньо використаний в інструкції VPCMOV - векторизованого умовного пересилання.
Інструкція | Опис[9] | immediate | Порівняння |
---|---|---|---|
VPCOMB
|
Compare Vector Signed Bytes | 000 | Менше |
VPCOMW
|
Compare Vector Signed Words | 001 | Менше або дорівнює |
VPCOMD
|
Compare Vector Signed Doublewords | 010 | Більше |
VPCOMQ
|
Compare Vector Signed Quadwords | 011 | Більше ніж або дорівнює |
VPCOMUB
|
Compare Vector Unsigned Bytes | 100 | Дорівнює |
VPCOMUW
|
Compare Vector Unsigned Words | 101 | Не дорівнює |
VPCOMUD
|
Compare Vector Unsigned Doublewords | 110 | Завжди брехливе |
VPCOMUQ
|
Compare Vector Unsigned Quadwords | 111 | Завжди істинне |
VPCMOV працює як побітовий варіант інструкцій blend із SSE4. Для кожного біта операнда-селектора, рівного 1, виділяє підсумковий біт з першого джерела, якщо біт у селекторі дорівнює 0, вибирає підсумковий біт з другого джерела. При використанні спільно з векторними операціями порівняння XOP дозволяє реалізувати векторний тернарний оператор, або якщо в ролі другого аргументу виступає регістр призначення, умовне умовне пересилання (CMOV).
Інструкція | Опис[9] |
---|---|
VPCMOV
|
Vector Conditional Move |
Інструкції зсуву відрізняються від подібних до набору інструкцій SSE2 в тому, що вони можуть зрушувати кожен елемент на різну кількість біт, використовуючи знакові цілі числа, що упаковані, з векторного регістра. Знак вказує напрямок зсуву або повороту, позитивні значення для зсуву вліво і негативні - для зсуву вправо [10] Корпорація Intel реалізувала інший, несумісний набір змінних векторних зсувів та поворотів а AVX2.[11]
Інструкція | Опис[9] |
---|---|
VPROTB
|
Packed Rotate Bytes |
VPROTW
|
Packed Rotate Words |
VPROTD
|
Packed Rotate Doublewords |
VPROTQ
|
Packed Rotate Quadwords |
VPSHAB
|
Packed Shift Arithmetic Bytes |
VPSHAW
|
Packed Shift Arithmetic Words |
VPSHAD
|
Packed Shift Arithmetic Doublewords |
VPSHAQ
|
Packed Shift Arithmetic Quadwords |
VPSHLB
|
Packed Shift Logical Bytes |
VPSHLW
|
Packed Shift Logical Words |
VPSHLD
|
Packed Shift Logical Doublewords |
VPSHLQ
|
Packed Shift Logical Quadwords |
VPPERM — єдина інструкція, яка поєднує інструкції PALIGNR і PSHUFB з SSSE3 і розширює їх. Деякі порівнюють її з AltiVec інструкцією VPERM.[12] Вона приймає три регістри на вхід: два джерела та селектор (третій). Кожен байт у селекторі вибирає один із байтів в одному з двох джерел для запису у вихідний регістр. Селектор може вибирати нульовий байт, змінювати порядок біт на зворотний, повторювати значний біт. Всі ефекти або входи можуть бути інвертовані.
Інструкції VPPERMIL2PD та VPPERMIL2PS – двооперандні варіанти інструкцій VPERMILPD та VPERMILPS з набору AVX. Вони, як і VPPERM, можуть вибрати вихідне значення з будь-яких полів двох вхідних регістрів.
Інструкція | Опис[9] |
---|---|
VPPERM
|
Packed Permute Byte |
VPPERMIL2PD
|
Permute Two-Source Double-Precision Floating-Point |
VPPERMIL2PS
|
Permute Two-Source Single-Precision Floating-Point |
Ці інструкції виділяють дрібну частину з упакованих чисел із рухомою комою. Така частина числа може бути втрачена при перетворенні їх на ціле.
Інструкція | Опис[9] |
---|---|
VPCMOV
|
Vector Conditional Move |
But with Zen being a clean-sheet design, there are some instruction set extensions found in Bulldozer processors not found in Zen/znver1. Those no longer present include FMA4 and XOP.