Хранение регистра общего назначения в st0 - PullRequest
2 голосов
/ 26 октября 2019

Если у меня есть какое-то значение (битовый шаблон, скажем, все нули) в rax, могу ли я сохранить его в st0 без сохранения и загрузки из памяти?

Ответы [ 2 ]

2 голосов
/ 26 октября 2019

Я думаю, что вы действительно хотите это для Инструкции с длинной задержкой , где movd / movq + sqrtss или sqrtsd работает легче, чем ?? -> fsqrt.

Соединение целочисленной зависимости в зависимость x87 можно выполнить с помощью fcmovcc через целочисленные флаги вместо передачи битового шаблона. На Skylake это инструкция с 4 мопами, но это 4 ALU мопс.

В другом направлении fcomi + setcc или cmovcc или даже просто fcom +fnstsw ax.

Как указывает @Hadi, вы можете создавать значения в регистрах x87 с fldz (1 моп) или fld1 (2 моп). Затем сделайте это зависимым от того, что вы хотите, используя fcmovne st0, st1 или аналогичный.


Возможный ответ, не совсем изученный, поскольку он вряд ли будет полезен для вас (возможно, с микрокодированием emms: 10 мопов на Skylake, 31 моп на Haswell.)

Возможно, вы можете использовать movq mm0, rax, а затем emms, чтобы выйти из состояния MMX . Это помечает все теги регистра x87 как «пустые».

На текущем AMD FEMMS идентична EMMS, согласно Справочному руководству по ISA PDF от ISA 2018-го мая , но я, кажется, напоминаюсчитая, что FEMMS на более старых процессорах AMD оставили регистры x87 неопределенными. Может быть, это пригодится для чего-то. Он по-прежнему устанавливает слова тега, поэтому неопределенное содержимое, вероятно, относится только к случаям, которые, возможно, ожидали найти содержимое mm0..7, все еще находящееся там после EMMS, и затем запустить другую инструкцию MMX. Или найти данные в состоянии fxsave.

64-разрядный MMX регистрирует псевдонимы значимостей (мантисс) 80-разрядных регистров x87. (я думаю). Стек st0..7 отображается на те базовые 80-битные регистры, которые начинаются с того, который проиндексирован 3-битным полем TOP в слове состояния x87. (http://www.ray.masmcode.com/tutorial/fpuchap1.htm хорошо описывает это по аналогии с револьверным стволом).

Я не уверен, действительно ли это можно использовать, но я не думаю, что emms очищает mm /Содержимое регистра, только теги x87. ( Запись Intel vol.2 для emms говорит: «Устанавливает пустые значения всех тегов в слове тега x87 FPU (все 1 с)»

Если плавающее-точечная инструкция загружает один из регистров в стеке регистров данных x87 FPU до того, как слово метки x87 FPU было сброшено инструкцией EMMS, может произойти переполнение стека регистров x87, что приведет к исключению с плавающей точкой x87 илиневерный результат.

Он говорит только "может", а не "будет". Возможно, с метаданными x87 в известном состоянии вы можете смешивать инструкции MMX и инструкции x87 с некоторым согласованным поведением? по крайней мере, для конкретной микроархитектуры.

Вы не можете прочитать регистр x87, у которого слово тега 11 (имеется в виду пустое), и funfree нет, просто ffree дляустановите для одного слова тега значение 11 (без влияния на указатель на верхнюю часть стека или его содержимое).

Вам потребуется fstenv и изменить слово тега в сохраненных метаданных состояния x87 (28 байт в том числезаполнение в 32/64-битном режиме), затем fldenv.

. Или вы можете иметь готовую предустановленную среду x87 для fldenv с некоторыми словами тега, установленными на not-в использовании. (Но Agner Fog даже не рассчитывает время этой инструкции. Очевидно, что она будет микрокодирована и, вероятно, медленна.) Вы могли бы использовать ее без emms, но это все еще одна микрокодированная инструкция.

related: Запрос о наследии 3DNow! набор инструкций имеет несколько ссылок, которые я недавно выкопал о femms и как мало 3dNow! может взаимодействовать с SSE. Хм, по-видимому, он по-прежнему устанавливает для слова тега все неиспользованные, но не сохраняет известное отображение между регистрами mm0..7 и x87.

1 голос
/ 26 октября 2019

Существует ряд инструкций, которые вы можете использовать для загрузки константы в стек регистров FPU. Я думаю, что наиболее полезными здесь являются FLD1 и FLDZ, которые загружают в стек +1,0 и +0,0 соответственно. Если единственными возможными целыми числами, которые может содержать RAX, являются 1 и 0, то вы можете условно выполнить FLD1 или FLDZ.

Как правило, любое 64-разрядное целое число в формате без знака или двух дополнительных может быть представлено в 80-разрядном формате с плавающей точкой с расширенной точностью. Можно загрузить любое целое значение, найденное в RAX, в стек FPU с нулевым доступом к памяти. Это может быть достигнуто с помощью серии арифметических команд x87, возможно, выполняемых в цикле, счетчик отключений которого поддерживается в регистре GP. Одним из способов будет использование FADD (или FSUB для отрицательных целых чисел), пока st0 не будет содержать желаемое целочисленное значение, хотя это может быть очень медленным для больших (абсолютных) значений. Одна из возможных оптимизаций, которая работает для целых чисел, имеющих степени 2, состоит в том, чтобы загрузить константу +1,0, добавить одну, используя FADD, чтобы получить число 2, а затем использовать FMUL, пока не будет достигнута желаемая степень 2. Другой метод, который может быть быстрее в некоторых случаях, состоит в том, чтобы сначала разложить целое число в RAX, построить каждый из простых множителей, используя FADD, а затем умножить простые множители, используя FMUL.

Всеэти инструкции поддерживаются на всех процессорах Intel и AMD x86.

...