À partir de Pentium Pro (microarchitecture P6), Intel a repensé ses microprocesseurs et utilisé le noyau RISC interne sous les anciennes instructions CISC. Depuis Pentium Pro, toutes les instructions CISC sont divisées en parties plus petites (uops) puis exécutées par le noyau RISC.
Au début, il était clair pour moi qu'Intel avait décidé de cacher la nouvelle architecture interne et de forcer les programmeurs à utiliser "CISC Shell". Grâce à cette décision, Intel pourrait entièrement repenser l'architecture des microprocesseurs sans casser la compatibilité, c'est raisonnable.
Cependant, je ne comprends pas une chose, pourquoi Intel garde-t-il un ensemble d'instructions RISC interne caché pendant tant d'années? Pourquoi ne laisseraient-ils pas les programmeurs utiliser des instructions RISC comme l'ancien jeu d'instructions CISC x86?
Si Intel conserve la compatibilité descendante pendant si longtemps (nous avons toujours le mode 8086 virtuel à côté du mode 64 bits), pourquoi ne nous permettent-ils pas de compiler des programmes afin qu'ils contournent les instructions CISC et utilisent directement le noyau RISC? Cela ouvrira une voie naturelle pour abandonner lentement le jeu d'instructions x86, ce qui est obsolète de nos jours (c'est la principale raison pour laquelle Intel a décidé d'utiliser le noyau RISC à l'intérieur, non?).
En regardant la nouvelle série Intel 'Core i' je vois, qu'ils étendent uniquement le jeu d'instructions CISC en ajoutant AVX, SSE4 et autres.
Non, le jeu d'instructions x86 n'est certainement pas obsolète. Il est toujours aussi populaire. Intel utilise un ensemble de micro-instructions de type RISC en interne parce qu'elles peuvent être traitées plus efficacement.
Ainsi, un processeur x86 fonctionne en ayant un décodeur assez robuste dans le frontend, qui accepte les instructions x86 et les convertit en un format interne optimisé, que le backend peut traiter.
Quant à exposer ce format à des programmes "externes", il y a deux points:
Ce n'est pas tout à fait un arrangement parfait, mais le coût est assez faible, et c'est un bien meilleur choix que de concevoir le CPU pour prendre en charge deux jeux d'instructions complètement différents. (Dans ce cas, ils finiraient probablement par inventer un troisième ensemble de micro-opérations à usage interne, simplement parce que celles-ci peuvent être modifiées librement pour s'adapter au mieux à l'architecture interne du CPU)
La vraie réponse est simple.
Le principal facteur derrière la mise en œuvre des processeurs RISC a été de réduire la complexité et de gagner en vitesse. L'inconvénient de RISC est la densité d'instructions réduite, ce qui signifie que le même code exprimé au format RISC a besoin de plus d'instructions que le code CISC équivalent.
Cet effet secondaire ne signifie pas grand-chose si votre processeur fonctionne à la même vitesse que la mémoire, ou du moins si les deux fonctionnent à des vitesses raisonnablement similaires.
Actuellement, la vitesse de la mémoire par rapport à la vitesse du processeur montre une grande différence d'horloges. Les processeurs actuels sont parfois cinq fois ou plus rapides que la mémoire principale.
Cet état de la technologie favorise un code plus dense, ce que fournit le CISC.
Vous pouvez affirmer que les caches pourraient accélérer les processeurs RISC. Mais la même chose peut être dite à propos des CPU du CISC.
Vous obtenez une amélioration de la vitesse plus importante en utilisant CISC et les caches que RISC et les caches, car le cache de même taille a plus d'effet sur le code haute densité que fournit CISC.
Un autre effet secondaire est que RISC est plus difficile sur l'implémentation du compilateur. Il est plus facile d'optimiser les compilateurs pour les processeurs CISC. etc.
Intel sait ce qu'ils font.
C'est tellement vrai que ARM a un mode de densité de code plus élevé appelé Thumb.
Si Intel conserve la compatibilité descendante pendant si longtemps (nous avons toujours le mode 8086 virtuel à côté du mode 64 bits), pourquoi ne nous permettent-ils pas de compiler des programmes afin qu'ils contournent les instructions CISC et utilisent directement le noyau RISC? Cela ouvrira une voie naturelle pour abandonner lentement le jeu d'instructions x86, ce qui est obsolète de nos jours (c'est la principale raison pour laquelle Intel a décidé d'utiliser le noyau RISC à l'intérieur, non?).
Vous devez examiner l'angle commercial de cela. Intel a en fait essayé de s'éloigner de x86, mais c'est l'oie qui pond des œufs d'or à l'entreprise. XScale et Itanium n'ont jamais atteint le niveau de succès de leur cœur de métier x86.
Ce que vous demandez essentiellement, c'est qu'Intel se fende les poignets en échange de flous chaleureux des développeurs. Miner x86 n'est pas dans leur intérêt. Tout ce qui empêche plus de développeurs de choisir de cibler x86 sape x86. Cela, à son tour, les mine.
La réponse est simple. Intel ne développe pas de CPU pour développeurs! Ils les développent pour les personnes qui prennent les décisions achats, ce que BTW, c'est ce que fait chaque entreprise dans le monde!
Intel a depuis longtemps pris l'engagement que (dans des limites raisonnables, bien sûr), leurs CPU resteraient rétrocompatibles. Les gens veulent savoir que, lorsqu'ils achètent un nouvel ordinateur Intel, que tous de leur logiciel actuel fonctionneront exactement même chose que sur leur ancien ordinateur. (Bien que, espérons-le, plus rapide!)
De plus, Intel sait exactement à quel point cet engagement est important, car il a déjà essayé de suivre une voie différente. Combien de personnes exactement connaissez-vous avec un processeur Itanium?!?
Vous ne l'aimerez peut-être pas, mais cette décision, de rester avec le x86, est ce qui a fait d'Intel l'un des noms commerciaux les plus reconnaissables au monde!
La réponse de @ jalf couvre la plupart des raisons, mais il y a un détail intéressant qu'il ne mentionne pas: le noyau interne de type RISC n'est pas conçu pour exécuter un ensemble d'instructions comme ARM/PPC/MIPS. La taxe x86 n'est pas seulement payée dans les décodeurs énergivores, mais dans une certaine mesure dans le cœur. c'est-à-dire que ce n'est pas seulement l'encodage des instructions x86; c'est chaque instruction avec une sémantique bizarre.
Imaginons qu'Intel ait créé un mode de fonctionnement où le flux d'instructions était autre que x86, avec des instructions plus directement liées à uops. Imaginons également que chaque modèle de processeur possède son propre ISA pour ce mode, ils sont donc toujours libres de changer les internes quand ils le souhaitent et de les exposer avec un minimum de transistors pour l'instruction- décoder de ce format alternatif.
Vraisemblablement, vous n'auriez toujours que le même nombre de registres, mappés à l'état architectural x86, de sorte que les systèmes d'exploitation x86 peuvent l'enregistrer/restaurer sur des commutateurs de contexte sans utiliser le jeu d'instructions spécifique au processeur. Mais si nous supprimons cette limitation pratique, oui, nous pourrions avoir quelques registres de plus car nous pouvons utiliser les registres de température cachés normalement réservés au microcode1.
Si nous n'avons que des décodeurs alternatifs sans modification des étapes ultérieures du pipeline (unités d'exécution), ceci ISA aurait toujours de nombreuses excentricités x86. Ce ne serait pas une architecture RISC très agréable. Aucune instruction unique ne serait très complexe, mais une partie de la folie de x86 serait toujours là.
Par exemple: les décalages gauche/droite laissent l'indicateur de débordement indéfini, sauf si le nombre de décalages est un, auquel cas OF = la détection de débordement signée habituelle. Folie similaire pour les rotations. Cependant, les instructions RISC exposées peuvent fournir des décalages sans indicateur, etc. (permettant l'utilisation d'un ou deux des multiples uops qui entrent généralement dans certaines instructions x86 complexes). Donc, cela ne constitue pas vraiment le principal contre-argument.
Si vous allez créer un tout nouveau décodeur pour un RISC ISA, vous pouvez le faire choisir et choisir des parties d'instructions x86 à exposer en tant qu'instructions RISC. Cela atténue quelque peu la spécialisation x86 du noyau.
Le codage des instructions ne serait probablement pas de taille fixe, car les uops simples peuvent contenir beaucoup de données. Beaucoup plus de données que de sens si toutes les insns sont de la même taille. Un uop micro-fusionné unique peut ajouter un immédiat 32 bits et un opérande mémoire qui utilise un mode d'adressage avec 2 registres et un déplacement 32 bits. (Dans SnB et versions ultérieures, seuls les modes d'adressage à registre unique peuvent micro-fusionner avec des opérations ALU).
uops sont très grands et pas très similaires aux instructions à largeur fixe ARM. Un jeu d'instructions à largeur fixe 32 bits ne peut charger que des éléments 16 bits à la fois, donc le chargement d'une adresse 32 bits nécessite un chargement- paire immédiatement inférieure à faible/charge élevée immédiate. x86 n'a pas à faire cela, ce qui ne lui permet pas d'être terrible avec seulement 15 registres GP limitant la possibilité de garder des constantes dans les registres. (15 est une grande aide sur 7 registres, mais doubler à nouveau à 31 aide beaucoup moins, je pense qu'une simulation a été trouvée. RSP n'est généralement pas à usage général, donc c'est plus comme 15 registres GP et une pile.)
TL; Résumé DR:
Quoi qu'il en soit, cette réponse se résume à "le jeu d'instructions x86 est probablement le meilleur moyen de programmer un processeur qui doit être capable d'exécuter rapidement des instructions x86", mais nous espérons que cela nous éclairera sur les raisons.
Formats uop internes dans le front-end vs back-end
Voir aussi Micro fusion et modes d'adressage pour un cas de différences dans ce que les formats uop frontaux et back-end peuvent représenter sur les processeurs Intel.
Note de bas de page 1 : Il existe des registres "cachés" à utiliser comme temporaires par le microcode. Ces registres sont renommés comme les registres d'architecture x86, de sorte que les instructions multi-uop peuvent s'exécuter dans le désordre.
par exemple. xchg eax, ecx
sur les processeurs Intel décode en 3 uops ( pourquoi? ), et notre meilleure supposition est que ce sont des uops de type MOV qui font tmp = eax; ecx=eax ; eax=tmp;
. Dans cet ordre, car je mesure la latence de la direction dst-> src à ~ 1 cycle, contre 2 pour l'autre. Et ces mouvements ne sont pas comme des instructions régulières de mov
; ils ne semblent pas être candidats à l'élimination des mouvements sans latence.
Voir aussi http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ pour une mention d'essayer de mesurer expérimentalement la taille du PRF et d'avoir à tenir compte des registres physiques utilisés pour contenir état architectural, y compris les registres cachés.
Dans le front-end après les décodeurs, mais avant l'étape d'émission/renommage qui renomme les registres sur le fichier de registre physique, le format uop interne utilise des numéros de registre similaires aux numéros de registre x86, mais avec de l'espace pour résoudre ces registres cachés.
Le format uop est quelque peu différent à l'intérieur du noyau hors service (ROB et RS), alias back-end (après l'étape d'émission/de renommage). Les fichiers de registres physiques int/FP chacun a 168 entrées dans Haswell , donc chaque champ de registre dans un uop doit être suffisamment large pour en traiter autant.
Puisque le renamer est là dans le HW, nous serions probablement mieux de l'utiliser, au lieu de fournir des instructions planifiées directement au back-end. Nous devions donc travailler avec un ensemble de registres aussi volumineux que les registres architecturaux x86 + les microcodes temporaires, pas plus que cela.
Le back-end est conçu pour fonctionner avec un renamer frontal qui évite les dangers WAW/WAR, donc nous ne pouvons pas l'utiliser comme un CPU en ordre même si nous le voulions. Il n'a pas de verrouillage pour détecter ces dépendances; qui est géré par issue/rename.
Cela pourrait être bien si nous pouvions alimenter le back-end sans le goulot d'étranglement de l'étape de problème/renommage (le point le plus étroit des pipelines Intel modernes, par exemple 4 larges sur Skylake vs 4 ALU + 2 charge + 1 ports de magasin dans le back-end). Mais si vous faisiez cela, je ne pense pas que vous puissiez planifier statiquement du code pour éviter la réutilisation des registres et marcher sur un résultat qui est toujours nécessaire si un cache-miss bloquait une charge pendant longtemps.
Nous avons donc à peu près besoin d'alimenter les uops à l'étape de problème/renommage, probablement en contournant uniquement le décodage, pas le cache uop ou IDQ. Ensuite, nous obtenons un exécutable OoO normal avec une détection des dangers sains. La table d'allocation des registres est uniquement conçue pour renommer 16 + quelques registres entiers sur le PRF entier à 168 entrées. Nous ne pouvions pas nous attendre à ce que le matériel informatique renomme un plus grand ensemble de registres logiques sur le même nombre de registres physiques; cela prendrait un RAT plus grand.