Ответ @jalf охватывает большинство причин, но есть одна интересная деталь, о которой он не упоминает: внутреннее RISC-подобное ядро не предназначено для запуска набора инструкций, например ARM / PPC / MIPS. Налог на x86 уплачивается не только за энергоемкие декодеры, но и в некоторой степени за все ядро. т.е. это не просто кодировка инструкций x86; это каждая инструкция со странной семантикой.
Давайте представим, что Intel действительно создала рабочий режим, в котором поток инструкций отличался от x86, с инструкциями, которые более точно отображались на uops. Давайте также представим, что каждая модель процессора имеет свой собственный ISA для этого режима, поэтому они по-прежнему могут изменять внутренние компоненты, когда им нравится, и открывать их с минимальным количеством транзисторов для декодирования инструкций этого альтернативного формата.
Предположительно, у вас все еще будет только такое же количество регистров, сопоставленных с архитектурным состоянием x86, поэтому операционные системы x86 могут сохранять / восстанавливать его при переключении контекста без использования набора инструкций для конкретного процессора. Но если мы отбросим это практическое ограничение, да, мы могли бы иметь еще несколько регистров, потому что мы можем использовать скрытые временные регистры, обычно зарезервированные для микрокода 1 .
Если бы у нас были просто альтернативные декодеры без каких-либо изменений в более поздних этапах конвейера (исполнительных модулях), этот ISA все равно имел бы много эксцентриситетов x86. Это была бы не очень хорошая RISC-архитектура. Никакая отдельная инструкция не может быть очень сложной, но некоторые другие безумия x86 все же присутствуют.
Например: сдвиги влево / вправо оставляют флаг переполнения неопределенным, если только счетчик сдвигов не равен единице, и в этом случае OF = обычное обнаружение переполнения со знаком. Подобное безумие для вращений. Однако открытые инструкции RISC могут обеспечивать сдвиги без флагов и т. Д. (Позволяя использовать только один или два из множества мопов, которые обычно входят в некоторые сложные инструкции x86). Так что это не самый главный контраргумент.
Если вы собираетесь создать совершенно новый декодер для RISC ISA, вы можете попросить его выбрать части инструкций x86, которые будут представлены как инструкции RISC. Это несколько смягчает x86-специализацию ядра.
Кодирование инструкций, вероятно, не будет фиксированным, поскольку отдельные мопы могут содержать много данных. Гораздо больше данных, чем имеет смысл, если все insns имеют одинаковый размер. Один микроплавленный uop может добавить 32-битный непосредственный операнд и операнд памяти, который использует режим адресации с 2 регистрами и 32-битным смещением. (В SnB и более поздних версиях только режимы адресации с одним регистром могут соединяться с операциями ALU).
uops очень большие и не очень похожи на инструкции ARM фиксированной ширины. 32-битный набор инструкций фиксированной ширины может загружать только 16 битов одновременно, поэтому для загрузки 32-битного адреса требуется пара "загрузка-немедленная" низкая половина / загрузка высокая-немедленная. x86 не обязан этого делать, что помогает не быть ужасным: всего 15 регистров GP ограничивают возможность хранения констант в регистрах. (15 - это большая помощь по сравнению с 7 регистрами, но удвоение снова до 31 помогает намного меньше, я думаю, что была обнаружена некоторая имитация. RSP обычно не является универсальным, поэтому он больше похож на 15 регистров GP и стек.)
TL; Резюме DR:
В любом случае, этот ответ сводится к тому, что «набор инструкций x86, вероятно, лучший способ запрограммировать процессор, который должен иметь возможность быстро выполнять инструкции x86», но, надеюсь, проливает свет на причины.
Внутренние форматы uop в интерфейсе по сравнению с сервером
См. Также Micro fusion и режимы адресации, чтобы узнать о различиях в том, что форматы интерфейсных и внутренних модулей uop могут представлять на процессорах Intel.
Сноска 1 : Есть несколько «скрытых» регистров для использования микрокодом в качестве временных. Эти регистры переименовываются так же, как регистры архитектуры x86, поэтому многопозиционные инструкции могут выполняться не по порядку.
например, xchg eax, ecx
на процессорах Intel декодируется как 3 мупа ( почему? ), и мы предполагаем, что это MOV-подобные мопы tmp = eax; ecx=eax ; eax=tmp;
. В таком порядке, потому что я измеряю задержку в направлении dst-> src на ~ 1 такте, а не 2 в другом случае. И эти команды перемещения не похожи на обычные mov
инструкции; они не кажутся кандидатами на удаление mov с нулевой задержкой.
См. Также http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/, где упоминается попытка экспериментального измерения размера PRF и необходимость учета физических регистров, используемых для хранения архитектурного состояния, включая скрытые регистры.
Во внешнем интерфейсе после декодеров, но до этапа выдачи / переименования, который переименовывает регистры в физический файл регистров, внутренний формат uop использует номера регистров, аналогичные номерам регистров x86, но с местом для адресации этих скрытых регистров.
Формат uop несколько отличается внутри ядра вне очереди (ROB и RS), также известного как back-end (после этапа выдачи / переименования). Каждый файл физических регистров int / FP имеет 168 записей в Haswell , поэтому каждое поле регистра в uop должно быть достаточно широким, чтобы адресовать такое количество.
Поскольку переименователь присутствует в HW, нам, вероятно, было бы лучше использовать его, вместо того, чтобы передавать статически запланированные инструкции непосредственно в серверную часть. Таким образом, мы могли бы работать с набором регистров размером с регистры архитектуры x86 + временные памяти микрокода, не более того.
Серверная часть разработана для работы с переименователем внешнего интерфейса, который позволяет избежать опасностей WAW / WAR, поэтому мы не могли бы использовать его как упорядоченный ЦП, даже если бы захотели. У него нет блокировок для обнаружения этих зависимостей; это обрабатывается проблемой / переименованием.
Было бы неплохо, если бы мы могли передавать uops в серверную часть без узкого места на этапе выдачи / переименования (самое узкое место в современных конвейерах Intel, например, 4-х разрядный в Skylake против 4 ALU + 2 порта загрузки + 1 порт хранения в бэкэнд). Но если вы это сделали, я не думаю, что вы можете статически запланировать код, чтобы избежать повторного использования регистров и наступления на результат, который все еще необходим, если из-за промаха кеша загрузка застопорилась на долгое время.
Таким образом, нам в значительной степени нужно направить мопы на этап выдачи / переименования, вероятно, только в обход декодирования, а не кеш-кеш или IDQ. Тогда мы получаем нормальный OoO exec с нормальным обнаружением опасности. Таблица распределения регистров предназначена только для переименования 16 + нескольких целочисленных регистров в целочисленный PRF из 168 записей. Мы не могли ожидать, что HW переименует больший набор логических регистров в то же количество физических регистров; для этого потребуется большая RAT.