A resposta de @jalf cobre a maioria dos motivos, mas há um detalhe interessante que ele não menciona: o núcleo interno semelhante ao RISC não foi projetado para executar um conjunto de instruções como ARM / PPC / MIPS. O imposto x86 não é pago apenas nos decodificadores que consomem muita energia, mas até certo ponto em todo o núcleo. ou seja, não é apenas a codificação da instrução x86; é cada instrução com uma semântica estranha.
Vamos fingir que a Intel criou um modo operacional em que o fluxo de instruções era diferente de x86, com instruções mapeadas mais diretamente para uops. Vamos também fingir que cada modelo de CPU tem seu próprio ISA para este modo, então eles ainda estão livres para alterar os internos quando quiserem e expô-los com uma quantidade mínima de transistores para decodificação de instruções deste formato alternativo.
Presumivelmente, você ainda teria apenas o mesmo número de registros, mapeados para o estado arquitetônico x86, de modo que os sistemas operacionais x86 podem salvá-lo / restaurá-lo em alternâncias de contexto sem usar o conjunto de instruções específico da CPU. Mas se descartarmos essa limitação prática, sim, poderíamos ter mais alguns registros porque podemos usar os registros temporários ocultos normalmente reservados para o microcódigo 1 .
Se apenas tivermos decodificadores alternativos sem alterações nos estágios posteriores do pipeline (unidades de execução), este ISA ainda terá muitas excentricidades x86. Não seria uma arquitetura RISC muito boa. Nenhuma instrução seria muito complexa, mas algumas das outras loucuras do x86 ainda estariam lá.
Por exemplo: os deslocamentos para a esquerda / direita deixam o sinalizador de estouro indefinido, a menos que a contagem de deslocamento seja um, caso em que OF = a detecção usual de estouro com sinal. Loucura semelhante para gira. No entanto, as instruções RISC expostas podem fornecer mudanças sem sinalizador e assim por diante (permitindo o uso de apenas um ou dois dos vários uops que geralmente entram em algumas instruções x86 complexas). Portanto, isso realmente não se sustenta como o principal contra-argumento.
Se você for fazer um decodificador totalmente novo para um ISA RISC, poderá fazer com que ele selecione partes das instruções x86 para serem expostas como instruções RISC. Isso atenua um pouco a especialização x86 do núcleo.
A codificação da instrução provavelmente não seria de tamanho fixo, uma vez que uops individuais podem conter muitos dados. Muito mais dados do que faz sentido se todos os insns forem do mesmo tamanho. Um único uop micro-fundido pode adicionar um operando imediato de 32 bits e um operando de memória que usa um modo de endereçamento com 2 registradores e um deslocamento de 32 bits. (No SnB e posterior, apenas os modos de endereçamento de registro único podem microfundir com operações de ALU).
uops são muito grandes e não muito semelhantes às instruções ARM de largura fixa. Um conjunto de instruções de 32 bits de largura fixa só pode carregar imediatos de 16 bits por vez, portanto, o carregamento de um endereço de 32 bits requer um par de carga imediata baixa-metade / carga alta-imediata. O x86 não precisa fazer isso, o que o ajuda a não ser terrível, com apenas 15 registros GP limitando a capacidade de manter constantes nos registros. (15 é uma grande ajuda sobre 7 registros, mas dobrar novamente para 31 ajuda muito menos, eu acho que alguma simulação encontrada. RSP geralmente não é de uso geral, então é mais como 15 registros GP e uma pilha.)
TL; Resumo DR:
De qualquer forma, essa resposta se resume a "o conjunto de instruções x86 é provavelmente a melhor maneira de programar uma CPU que deve ser capaz de executar instruções x86 rapidamente", mas espero que esclareça as razões.
Formatos uop internos no front-end vs. back-end
Veja também Micro fusão e modos de endereçamento para um caso de diferenças no que os formatos uop front-end vs. back-end podem representar nas CPUs Intel.
Nota de rodapé 1 : Existem alguns registros "ocultos" para uso como temporários por microcódigo. Esses registradores são renomeados da mesma forma que os registradores de arquitetura x86, de modo que as instruções multi-uop podem ser executadas fora de ordem.
por exemplo, xchg eax, ecx
em CPUs da Intel decodifica como 3 uops ( por quê? ), e nosso melhor palpite é que esses uops do tipo MOV o fazem tmp = eax; ecx=eax ; eax=tmp;
. Nessa ordem, porque eu meço a latência da direção dst-> src em ~ 1 ciclo, vs. 2 para o outro lado. E esses movimentos não são normaismov
instruções ; eles não parecem ser candidatos para eliminação de movimento de latência zero.
Veja também http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ para uma menção de tentar medir experimentalmente o tamanho do PRF e ter que levar em conta os registros físicos usados para manter o estado arquitetônico, incluindo registros ocultos.
No front-end após os decodificadores, mas antes do estágio de emissão / renomeação que renomeia os registros no arquivo de registro físico, o formato uop interno usa números de registro semelhantes aos números de registro x86, mas com espaço para lidar com esses registros ocultos.
O formato uop é um pouco diferente dentro do núcleo fora de ordem (ROB e RS), também conhecido como back-end (após o estágio de emissão / renomeação). Cada um dos arquivos de registro físico int / FP tem 168 entradas em Haswell , então cada campo de registro em um uop precisa ser largo o suficiente para lidar com esse número.
Como o renomeador está no HW, provavelmente seria melhor usá-lo, em vez de alimentar instruções programadas estaticamente diretamente no back-end. Portanto, trabalharíamos com um conjunto de registros tão grande quanto os registros de arquitetura x86 + temporários de microcódigo, não mais do que isso.
O back-end foi projetado para funcionar com um renomeador de front-end que evita os riscos WAW / WAR, portanto, não poderíamos usá-lo como uma CPU em ordem, mesmo se quiséssemos. Ele não tem intertravamentos para detectar essas dependências; que é tratado por emitir / renomear.
Seria ótimo se pudéssemos alimentar uops no back-end sem o gargalo do estágio de edição / renomeação (o ponto mais estreito nos pipelines modernos da Intel, por exemplo, 4-wide no Skylake vs. 4 ALU + 2 load + 1 store ports em o back-end). Mas se você fez isso, não acho que você pode agendar código estaticamente para evitar a reutilização de registro e pisar em um resultado que ainda é necessário se uma falha de cache paralisar uma carga por um longo tempo.
Portanto, praticamente precisamos alimentar o uops para o estágio de emissão / renomeação, provavelmente ignorando a decodificação, não o cache uop ou IDQ. Então, obtemos exec normal OoO com detecção sã de perigo. A tabela de alocação de registro é projetada apenas para renomear 16 + alguns registros inteiros no PRF inteiro de 168 entradas. Não podemos esperar que o HW renomeie um conjunto maior de registros lógicos no mesmo número de registros físicos; isso exigiria um RAT maior.