Язык ассемблера эквивалентен Ceil, Floor - PullRequest
0 голосов
/ 06 ноября 2019

Что такое x86 эквивалент потолка, пола? Я не могу особенно Google соответствующие инструкции. Эквивалентом необязательно может быть одна инструкция, хотя предпочтительнее будет одна инструкция.

1 Ответ

1 голос
/ 07 ноября 2019

Этаж / потолок с одной инструкцией доступен только с SSE4.1 roundsd / roundpd, и только для XMM, не устаревшего x87.


С x87 вы устанавливаететекущий режим округления и затем используйте frndint. (http://www.ray.masmcode.com/tutorial/fpuchap1.htm показывает, где биты RC находятся в контрольном слове x87). Доступные режимы округления: ближайший-четный (по умолчанию), в направлении + Inf (ceil), в направлении -Inf (floor) и в направлении нуля (trunc).

Не забудьте установить режим округления обратно, когдавсе готово.

Очевидно, frndint медленно работает на некоторых процессорах (https://agner.org/optimize), так что на самом деле преобразование в целое число может быть быстрее и с fistp / fild (все еще срежим округления установлен соответствующим образом.) Но это работает только для значений FP, которые могут быть представлены в виде 64-разрядного целого числа со знаком (при условии, что вы используете операнд памяти qword). Вместо этого вы можете добавить / вычесть соответствующее магическое число (чтобы сделать значениедействительно большое принудительное округление.) Опять же, это может потребовать установки режима округления.

Конечно, если вы хотите (int)floor(x), тогда определенно просто fistp с установленным режимом округленияпо желанию.

В SSE3 вы можете использовать fisttp для усечения до нуля (он был добавлен для ускорения приведения C float-> int в коде, который все еще хочет использовать устаревший x87, даже если SSEдоступен).

floor == trunc для неотрицательных значений, чтобы вы могли воспользоваться эффективным усечением fisttp или SSE XMM для этого случая.


В SSE4.1 для скалярных double в регистрах XMM вы будете использовать roundsd для округления до ближайшего целочисленного значения double с выбранным вами режимом округления, определяемым какнепосредственный операнд. (Не преобразование, просто двойное> двойное округление, как frndint, поэтому оно работает для любого значения). Доступны упакованные и скалярные версии с одинарной и двойной точностью.

С SSE4.1, roundsd + cvtsd2si - ваш лучший выбор для (int)floor(x). Или , если вы знаете, что ваше значение неотрицательно, вы можете просто использовать SSE2 cvttsd2si. Обратите внимание на дополнительные t для «усечения». (То же самое для одинарной точности или для упакованного SIMD с cvtpd2dq.)

...