La risposta di @jalf copre la maggior parte dei motivi, ma c'è un dettaglio interessante che non menziona: il core interno simile a RISC non è progettato per eseguire un set di istruzioni qualcosa come ARM / PPC / MIPS. L'imposta x86 non viene pagata solo nei decoder assetati di energia, ma in una certa misura in tutto il core. cioè non è solo la codifica delle istruzioni x86; è ogni istruzione con una semantica strana.
Facciamo finta che Intel abbia creato una modalità operativa in cui il flusso di istruzioni fosse qualcosa di diverso da x86, con istruzioni che si mappavano più direttamente su uops. Facciamo anche finta che ogni modello di CPU abbia il proprio ISA per questa modalità, quindi sono ancora liberi di cambiare gli interni quando vogliono ed esporli con una quantità minima di transistor per la decodifica delle istruzioni di questo formato alternativo.
Presumibilmente avresti ancora solo lo stesso numero di registri, mappati allo stato dell'architettura x86, quindi i sistemi operativi x86 possono salvarlo / ripristinarlo sui cambi di contesto senza utilizzare il set di istruzioni specifico della CPU. Ma se eliminiamo quella limitazione pratica, sì, potremmo avere qualche altro registro perché possiamo usare i registri temporanei nascosti normalmente riservati al microcodice 1 .
Se avessimo solo decoder alternativi senza modifiche alle fasi successive della pipeline (unità di esecuzione), questo ISA avrebbe ancora molte eccentricità x86. Non sarebbe un'architettura RISC molto bella. Nessuna singola istruzione sarebbe molto complessa, ma alcune delle altre follie di x86 sarebbero ancora lì.
Ad esempio: gli spostamenti sinistra / destra lasciano il flag Overflow indefinito, a meno che il conteggio degli spostamenti non sia uno, nel qual caso OF = il solito rilevamento di overflow con segno. Follia simile per le rotazioni. Tuttavia, le istruzioni RISC esposte potrebbero fornire spostamenti senza flag e così via (consentendo l'uso di solo uno o due dei multipli uops che di solito vanno in alcune complesse istruzioni x86). Quindi questo non regge davvero come il principale contro-argomento.
Se hai intenzione di creare un decoder completamente nuovo per un ISA RISC, puoi farlo scegliere e scegliere parti delle istruzioni x86 da esporre come istruzioni RISC. Questo mitiga in qualche modo la specializzazione x86 del core.
La codifica delle istruzioni probabilmente non sarebbe di dimensioni fisse, dal momento che i singoli utenti possono contenere molti dati. Molti più dati di quanti abbiano senso se tutti gli insns hanno la stessa dimensione. Un singolo uop microfuso può aggiungere un immediato a 32 bit e un operando di memoria che utilizza una modalità di indirizzamento con 2 registri e uno spostamento a 32 bit. (In SnB e versioni successive, solo le modalità di indirizzamento a registro singolo possono micro-fusibili con le operazioni ALU).
uops sono molto grandi e non molto simili alle istruzioni ARM a larghezza fissa. Un set di istruzioni a 32 bit a larghezza fissa può caricare solo 16 bit immediati alla volta, quindi il caricamento di un indirizzo a 32 bit richiede una coppia di caricamento immediato basso metà / carico alto-immediato. x86 non deve farlo, il che aiuta a non essere terribile con solo 15 registri GP che limitano la capacità di mantenere costanti nei registri. (15 è un grande aiuto su 7 registri, ma raddoppiare di nuovo a 31 aiuta molto meno, penso che sia stata trovata qualche simulazione. RSP di solito non è di uso generale, quindi è più come 15 registri GP e uno stack.)
TL; Riepilogo DR:
Ad ogni modo, questa risposta si riduce a "il set di istruzioni x86 è probabilmente il modo migliore per programmare una CPU che deve essere in grado di eseguire rapidamente le istruzioni x86", ma si spera che faccia luce sui motivi.
Formati UOP interni nel front-end vs back-end
Vedi anche Micro fusione e modalità di indirizzamento per un caso di differenze in ciò che i formati uop front-end e back-end possono rappresentare sulle CPU Intel.
Nota 1 : ci sono alcuni registri "nascosti" da utilizzare come provvisori per microcodice. Questi registri vengono rinominati proprio come i registri architetturali x86, quindi le istruzioni multi-up possono essere eseguite fuori ordine.
ad es. xchg eax, ecx
su CPU Intel decodifica come 3 uops ( perché? ), e la nostra ipotesi migliore è che si tratti di uops MOV-like che lo fanno tmp = eax; ecx=eax ; eax=tmp;
. In quest'ordine, perché misuro la latenza della direzione dst-> src a ~ 1 ciclo, contro 2 per l'altro modo. E queste mosse non sono come le normali mov
istruzioni; non sembrano essere candidati per l'eliminazione dei movimenti a latenza zero.
Vedere anche http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ per un accenno al tentativo di misurare sperimentalmente la dimensione della PRF e al dover tenere conto dei registri fisici utilizzati per contenere lo stato dell'architettura, inclusi i registri nascosti.
Nel front-end dopo i decodificatori, ma prima della fase di emissione / rinomina che rinomina i registri sul file di registro fisico, il formato UOP interno utilizza numeri di registro simili ai numeri di registro x86, ma con spazio per indirizzare questi registri nascosti.
Il formato uop è leggermente diverso all'interno del core out-of-order (ROB e RS), noto anche come back-end (dopo la fase di emissione / rinomina). I file di registro fisico int / FP hanno ciascuno 168 voci in Haswell , quindi ogni campo di registro in un uop deve essere sufficientemente ampio da indirizzarne molti.
Dato che il renamer è presente nell'HW, probabilmente sarebbe meglio usarlo, invece di fornire istruzioni programmate staticamente direttamente al back-end. Quindi potremmo lavorare con un set di registri grande quanto i registri architetturali x86 + i provvisori del microcodice, non di più.
Il back-end è progettato per funzionare con un renamer front-end che evita i pericoli WAW / WAR, quindi non potremmo usarlo come una CPU in ordine anche se lo volessimo. Non dispone di interblocchi per rilevare tali dipendenze; che viene gestito da problema / rinomina.
Potrebbe essere carino se potessimo alimentare gli uops nel back-end senza il collo di bottiglia della fase di emissione / rinomina (il punto più stretto nelle moderne pipeline Intel, ad esempio 4-wide su Skylake contro 4 ALU + 2 load + 1 store port in il back-end). Ma se lo hai fatto, non penso che tu possa programmare staticamente il codice per evitare il riutilizzo del registro e calpestare un risultato che è ancora necessario se un errore nella cache ha bloccato un carico per molto tempo.
Quindi abbiamo praticamente bisogno di alimentare gli uop nella fase di rilascio / rinomina, probabilmente bypassando solo la decodifica, non la cache uop o IDQ. Quindi otteniamo un normale dirigente OoO con una sana rilevazione dei rischi. La tabella di allocazione dei registri è progettata solo per rinominare 16 + alcuni registri interi nella PRF intera da 168 voci. Non ci si poteva aspettare che l'HW rinominasse un insieme più grande di registri logici sullo stesso numero di registri fisici; ciò richiederebbe un RAT più grande.