Запрос об устаревшей версии 3DNow! набор инструкций

Ради интереса я просматриваю устаревшие (устаревшие) инструкции от 3DNow! set, представленный AMD, и я пытаюсь понять, как они использовались. Кажется, что все инструкции закодированы по этому шаблону:

instruction destination_MMn_register_operand, source_MMn_register_or_memory_operand

где destinationRegister = destinationRegister -операция- source

Как, например, pfadd mm0, mmword ptr [rcx] (0F 0F 01 9E):

введите здесь описание изображения

Добавит 2 упакованных числа с плавающей запятой из памяти, на которую указывает rcx, к 2 упакованным числам с плавающей запятой, хранящимся в mm0, и сохранит результат в mm0.

Похоже, что эти инструкции 3DNow всегда имеют регистр mm в качестве пункта назначения.

Но как вы должны были получить результаты из этих mm регистров?

Другими словами, нет инструкций mov mmword ptr [rcx], mm0 или mov rax, mm0.


person MikeF    schedule 06.08.2018    source источник


Ответы (2)


Как говорит @harold, сохранение в памяти уже покрывается MMX movd или _2 _ + _ 3_ для извлечения только высокого float.

Единственное, чего вы не можете сделать, так это включить 3dNow! float в 80-битный float x87 без сохранения / перезагрузки.

Что могло бы быть потенциально полезным, так это версия EMMS, которая расширяет 32-битный float в 80-битный x87 long double в st0, а также устанавливает FPU обратно в режим x87 вместо режима MMX 1. Или, может быть, даже сделать это для нескольких регистров mm в несколько регистров x87?

то есть это был бы ярлык для movd dword [esp], mm0 / emms / fld dword [esp] для настройки дальнейшего скалярного FP после сокращения SIMD.

Помните, что это IEEE754 float; обычно они не нужны вам в целочисленных регистрах, если вы не разбираете их битовые поля (например, для реализации exp или log), но вы можете сделать это с помощью инструкций сдвига / маски MMX.


Но movd и fld дешевы, поэтому они не удосужились сделать специальную инструкцию только для того, чтобы сохранить задержку перезагрузки. Кроме того, реализация в виде отдельной инструкции могла быть медленной. Несмотря на то, что x86 не является RISC ISA, наличие одной действительно сложной инструкции часто медленнее, чем несколько более простых инструкций (особенно до того, как декодирование на несколько мопов было полноценным делом), например. Инструкции Intel и AMD sysenter и syscall по замене int 0x80 для системных вызовов требуют дополнительных инструкций до / после для сохранения большего количества состояния, но в целом они все же быстрее.

femms покидает MMX / 3dNow! От 3dNow! содержимое регистра не определено, только устанавливая слова тега как неиспользуемые, вместо того, чтобы сохранять отображение из регистров MMX в / из содержимого регистра x87. См. http://refspecs.linuxbase.org/AMD-3Dnow.pdf для официальное руководство AMD. IDK, если микроархитектура AMD просто сбросила информацию о переименовании регистров или что-то еще, но, вероятно, быстрое выполнение store / femms / x87-load позволяет сэкономить много транзисторов.

Или даже FEMMS все еще несколько медленный, поэтому они не хотят побуждать кодеров уходить / повторно входить в MMX / 3dNow! режим у всех часто.


Интересный факт: 3dNow! PREFETCHW (предварительная выборка с намерением записи) по-прежнему используется и имеет собственный бит функции CPUID.

См. Мой ответ на Каков эффект второго аргумента в _builtin_prefetch ()?

Вскоре процессоры Intel добавили поддержку декодирования его как NOP (поэтому программное обеспечение, такое как 64-битная Windows, может использовать его без проверки), но Broadwell и более поздние версии фактически выполняют предварительную выборку с RFO, чтобы получить строку кеша в состоянии MESI Exclusive, а не Shared, поэтому он может переключиться на Modified без дополнительного внешнего трафика.

Бит функции CPUID указывает, что он действительно выполняет предварительную выборку.


Сноска 1:

Помните, что регистры MMX являются псевдонимами регистров x87, поэтому для сохранения / восстановления архитектурного состояния при переключениях контекста не требовалось никакой поддержки новой ОС. Только после SSE мы получили новое архитектурное состояние. Так было до SSE2 + 3dNow! что 3dNow! float на SSE2 double может иметь смысл без переключения обратно в режим x87. И вы можете movq2dq xmm0, mm0 + _ 23_.

Они могли иметь float-> double в регистре mm, но оборудование fld / fst было разработано только для float или _28 _-> 80-битных и 80-битных -> _ 29_ или double. И вариант использования для этого ограничен; если вы используете 3dNow !, просто придерживайтесь float.

person Peter Cordes    schedule 06.08.2018
comment
Спасибо за информацию. Очень интересно. Кстати, после ознакомления с документацией AMD (ссылка на которую приведена в моем ответе) я заметил, что они относятся к числам с плавающей запятой одинарной точности, которые они используют для инструкций 3Dnow, как к имеющим 24-битное значение. Но насколько я понимаю, традиционные 32-битные числа с плавающей запятой Intel используют 23-битную мантиссу. Используют ли упакованные числа с плавающей запятой 3Dnow другой формат с плавающей запятой, чем Intel? - person MikeF; 07.08.2018
comment
@MikeF: Я так не думаю. Почти наверняка просто вопрос терминологии; AMD считает неявный бит в значении. В Википедии есть хорошая статья (en/wikipedia.org wiki /), который описывает IEEE binary32 как 24-битную точность, 23 сохраненных. (Для субнормальных чисел первый бит мантиссы равен 0, а не обычному 1. Таким образом, экспонента с полным нулем или без экспоненты подразумевает начальный бит.) Кстати, мантисса является предпочтительной терминологией, но более широко используется мантисса. Это то же самое. - person Peter Cordes; 07.08.2018
comment
Ох, хорошо. Мне было просто любопытно. Кто знает, AMD могла бы изобрести собственный формат с плавающей запятой. На данный момент это не имеет значения, поскольку 3DNow в любом случае почти на 99% мертв. Думаю, от него осталось только prefetchw инструкция. Windows использует его практически для каждого вызова режима ядра, чтобы предварительно загрузить туда некоторую структуру ядра. Что касается FEMMS инструкции, которую вы указали, я думаю, что это только AMD. Это было # UD'ing на всех моих системах Intel. - person MikeF; 07.08.2018
comment
@MikeF: Да, femms является частью 3dNow !, и не был принят как расширение MMX / SSE. Я упомянул об этом, потому что производители процессоров разрабатывают свои расширения набора инструкций так, чтобы они были удобны для их собственных текущих микроархитектур. (Другой пример этого: Intel SSE cvtsi2ss xmm0, eax оставляет верхние байты XMM0 без изменений, вероятно, поэтому он может быть единственным uop на Pentium III, который разбивает 128-битные векторные операции на 2. Но эта недальновидная ложная зависимость привела к выбору gcc к pxor xmm0,xmm0 во-первых, чтобы избежать риска создания цепочки деплоя, переносимой по петле, или соединения с медленной цепочкой деп. - person Peter Cordes; 07.08.2018
comment
О, Питер, тоже хотел воспитать. Поддерживает ли Intel инструкцию prefetch (без выборки для записи)? Похоже, что это только AMD, наследие набора 3Dnow, но в документации Intel на удивление ничего не говорится об этом. - person MikeF; 07.08.2018
comment
@MikeF: обычные prefetch уже давно поддерживаются Intel. felixcloutier.com/x86/PREFETCHh.html даже не перечисляет расширение ISA, поэтому может даже предшествовать MMX? В приложении к руководству NASM перечислено, когда insns были новыми, даже в 186. nasm.us/doc/nasmdocb .html говорит, что PREFETCH был новым в Pentium, а PREFETCHT0/1/2 / PREFETCHNTA был новым в Katmai (первое поколение PIII, так что я думаю, с SSE). IDK, что они имеют в виду под простым prefetch; возможно, существовала более ранняя версия кода операции, которая игнорировала поле /r в ModRM и просто загружалась заранее. - person Peter Cordes; 07.08.2018
comment
Ха, очень интересно. Спасибо, что поделился. Мне также было любопытно это странное поведение инструкции cvtsi2ss. Хотя ИМО, это одна из тех инструкций SISC, которые вам будет трудно найти в своем среднем коде. Что касается prefetch, то нет, я имел в виду еще более древнюю инструкцию. Тот, который имеет кодировку 0F 0D modR/M, тот, который даже не указывает, какой уровень кеширования использовать: L1, L2. - person MikeF; 07.08.2018
comment
@MikeF: Компиляторы все время используют cvtsi2sd в коде, который использует вместе FP и целочисленные значения (double чаще, чем float). например godbolt.org/g/M52CXv. SSE2 сохранил поведение ненужной зависимости и для этой инструкции, поэтому gcc испускает две инструкции dep-break pxor. (Clang более оптимистичен). Забавный трюк: с AVX вы можете использовать тот же обнуленный регистр в качестве источника без зависимости, например vcvtsi2sd xmm0, xmm7, eax, не уничтожая обнуленный регистр. Clang иногда использует это. Большая часть кода не подвергается автоматической векторизации, но по-прежнему актуальна для производительности. - person Peter Cordes; 07.08.2018
comment
@MikeF: Похоже, мое первое предположение было недостаточным для предварительной выборки 0F 0D, потому что очевидно, что это не та же кодировка, что и предварительная выборка SSE. IDK, почему руководство NASM помечает это как PENT,3DNOW. (Обратите внимание, что 0F 0D /1 - это предварительная выборка, поэтому поле / r должно иметь значение для предварительной выборки без записи на процессорах, которые фактически его реализуют. - person Peter Cordes; 07.08.2018

Собственно есть, а именно movd и movq. Эти инструкции не являются частью 3DNow !, они уже присутствовали в MMX, который 3DNow! является расширением. Вот почему 3DNow! включает очень неполный набор целочисленных операций.

person harold    schedule 06.08.2018