Все ли реализации x86-64 поддерживают инструкции CMOV cc? - PullRequest
2 голосов
/ 19 марта 2020

В моем ответе на вопрос Код ассемблера для возврата наименьшего целого числа в массиве вместо случайного возврата либо последнего, либо второго к последнему числу Я представил альтернативу, используя инструкцию cmovcc. Я сказал там:

Кажется, что инструкция cmov поддерживается всеми процессорами AMD64.

Однако в то время я еще не нашел убедительных источников для поддержки это утверждение. Поэтому я решил опубликовать этот вопрос, чтобы спросить об этом.

Ответы [ 2 ]

4 голосов
/ 19 марта 2020

Да, на практике все процессоры x86-64 поддерживают cmovcc, и широко распространено мнение, что его можно использовать без проверки бита функции CPUID. Т.е. бит функции, поддерживаемой длинным режимом, подразумевает это.


cmovcc был представлен с Intel P6 (PPro и т. Д.), Который предшествовал x86-64 и поддерживал на всех более поздних процессорах Intel (кроме Quark и KN C, которые не были предназначены для общего применения на основе P5 , но ни один из них не является x86-64 1 ) cmovcc также поддерживается первыми процессорами AMD64 (K8) и K7 до этого, но не K6. Процессоры Via x86-64 также поддерживают CMOV. Других производителей аппаратного обеспечения x86-64 AFAIK нет, и все программные эмуляторы включают CMOV как часть x86-64.

Различные другие производители продавали 32-разрядные ЦП с поддержкой CMOV, включая Cyrix 6x86MX / MII, возможно, некоторые обновление уровня бинарного перевода Transmeta Crusoe и Via C3 Nehemiah

Источники для поддержки 32-битных CMOV на различных процессорах: комментарии к Agner Fog's Stop the Instruction Set Сообщение в военном блоге, список реагирующих реагирований и обсуждение ошибки fedora .

Сноска 1: с тех пор и Quark, и KN C были прекращены. Quark был простым 32-битным микроконтроллером. KNF / KN C работает на Xeon Phi первого поколения с питанием и является его собственной особенностью: не полная совместимость с x86-64 , например, без CMOV или SSE, только предшественник AVX512, который он поддерживал. Я предполагаю, что у него был какой-то способ адресации более 4 ГБ ОЗУ. Xeon Phi KNL / KNM следующего поколения - это действительно x86-64 (производный от Silvermont) с cmov и обычным AVX + AVX512F. И также было прекращено.)


Все компиляторы для x86-64 предполагают, что при создании 64-битного кода безопасно использовать cmov.

Это важно, потому что компиляторы любят g cc не не предполагайте некоторые ранние дополнения к x86-64, если вы не используете специальные опции. например, lock cmpxchg16b (отсутствует в ранних версиях AMD) или lahf в длинном режиме (отсутствует в ранних версиях Intel P4, поддерживающих 64-разрядную версию). Тот факт, что G CC принимает принимает cmov со значением по умолчанию -march=x86-64, указывает на то, что предполагается универсальная поддержка.

(G CC обычно настроен на 32-битный режим Codegen предполагает, что Pentium Pro, тем не менее, также использует cmov, но не SSE1, например, return a ? b:c; компилируется в cmov с g cc -m32 такого же возраста, как 4.6 на Годболте . Это определенно не базовый уровень для 32-разрядного режима и сбой на P5 Pentium и более ранних версиях. G CC обычно настроен на работу с "i686" в 32-разрядном режиме, но действительно базовый x86-64 для 64-разрядного режима, потому что это все еще достаточно полно, чтобы не быть ужасным.)


Я не знаю, где вы найдете официальное подтверждение того, что это базовый уровень; В руководстве Intel (https://www.felixcloutier.com/x86/cmovcc) сказано следующее:

Команды CMOV cc были введены в процессорах семейства P6; однако эти инструкции может поддерживаться не всеми процессорами IA-32 . Программное обеспечение может определить, поддерживаются ли инструкции CMOV cc, путем проверки информации о функциях процессора с помощью инструкции CPUID (см. «CPUID - Идентификация CPU» в этой главе).

(соответствующий бит функции CPUID равен cpuid[EAX=1].EDX.bit15 ( песочница или с EAX = 8000_0000h), что также указывает на поддержку других функций P6, таких как fcomi и fcmovcc, если присутствует x87 FPU, то есть бит 0 того же самого Выход EDX установлен.)

Я думаю , что формулировка IA-32 подразумевает, что ни в одном процессоре IA-32e (название Intel для x86-64) его нет, только некоторые процессоры IA-32. Но это не очень четкое утверждение, и я мог бы переоценить его, основываясь на том факте, что знаю, что это правда на практике.


Другой ответ на этот вопрос указывает на SSE2. На практике все процессоры, которые поддерживают SSE2, также поддерживают cmov, но cmov не является «частью SSE2». У них есть отдельные биты CPUID. (И то, и другое является базовой для x86-64, поэтому 64-битному коду не нужно проверять функциональные биты.)

Ничто не помешает кому-то создать процессор с SSE2, но не cmov ... за исключением тот факт, что никто не будет покупать его, потому что он не может работать с обычными двоичными файлами. Многие современные компиляторы используют CMOV даже в 32-битном режиме, даже если они не по умолчанию используют SSE1. (Это может показаться немного глупым; количество процессоров PPro / PII, которые все еще используются, вероятно, не намного выше, чем P5 Pentium и совместимых процессоров. Но у полу-современного AMD Geode есть CMOV без SSE1. https://bugzilla.redhat.com/show_bug.cgi?id=538268#c9 )

0 голосов
/ 19 марта 2020

Здесь, на stackoverflow, я нашел ответ на Генерация инструкций CMOV с использованием компиляторов Microsoft , которая отвечает на мой вопрос в двух местах. Вот что:

Однако документация действительно подтверждает, что, как можно было бы ожидать, включение генерации кода SSE или SSE2 неявно разрешает использование условного -перемещать инструкции и все остальное, что было введено до SSE:

Помимо использования инструкций SSE и SSE2, компилятор также использует другие инструкции, присутствующие в ревизиях процессора которые поддерживают SSE и SSE2. Примером является инструкция CMOV, которая впервые появилась в ревизии Pentium Pro процессоров Intel.

И это:

Никаких специальных флагов компилятора или других соображений здесь необходимы, поскольку все процессоры, поддерживающие 64-битный режим, поддерживают условные перемещения.

Что касается первой башни цитат, если поддержка SSE2 подразумевает поддержку cmov, то 64 ISB-расширение также подразумевает cmov, поскольку хорошо известно, что x86-64 всегда поддерживает SSE2, как указано в статье в Википедии :

Архитектура AMD64 поддерживает IA -32 в качестве режима совместимости и включает SSE2 в свою спецификацию.

...