Lorsque les ingénieurs conçoivent une architecture de jeu d'instructions, par quelle procédure ou protocole, le cas échéant, suivent-ils lorsqu'ils désignent certains codes binaires comme instructions. Par exemple, si j'ai un ISA qui dit que 10110 est une instruction de chargement, d'où vient ce nombre binaire? A-t-il été modélisé à partir d'une table d'états pour une machine à états finis représentant une opération de chargement?
Edit: Après avoir fait plus de recherches, je crois que ce que j'essaie de demander concerne la façon dont les opcodes pour les différentes instructions CPU sont attribués. ADD peut être désigné par un opcode de 10011; une instruction de chargement pourrait être désignée comme 10110. Quel processus de réflexion va dans l'attribution de ces opcodes binaires pour l'ensemble d'instructions?
la source
Réponses:
Dans de nombreux cas, le choix est assez arbitraire ou basé sur «où cela convient le mieux» à mesure que les ISA se développent avec le temps. Cependant, le MOS 6502 est un merveilleux exemple de puce dont la conception ISA a été fortement influencée par la tentative de faire sortir autant que possible des transistors limités.
Regardez cette vidéo expliquant comment le 6502 a été rétroconçu , en particulier à partir de 34:20.
Le 6502 est un microprocesseur 8 bits introduit en 1975. Bien qu'il ait 60% moins de portes que le Z80, il était deux fois plus rapide, et bien qu'il soit plus contraint (en termes de registres, etc.), il compense cela avec un ensemble d'instructions élégant.
Il ne contient que 3510 transistors, qui ont été dessinés à la main par une petite équipe de personnes rampant sur de grandes feuilles de plastique qui ont ensuite été rétractées optiquement, formant les différentes couches du 6502.
Comme vous pouvez le voir ci-dessous, le 6502 transmet l'opcode d'instructions et les données de synchronisation dans la ROM de décodage, puis les transmet à un composant de "logique de contrôle aléatoire" dont le but est probablement de passer outre la sortie de la ROM dans certaines situations complexes.
À 37:00 dans la vidéo, vous pouvez voir un tableau de la ROM de décodage qui montre quelles conditions les entrées doivent remplir pour obtenir un "1" pour une sortie de contrôle donnée. Vous pouvez également le retrouver sur cette page .
Vous pouvez voir que la plupart des éléments de ce tableau ont des X dans différentes positions. Prenons par exemple
Cela signifie que les 3 premiers bits de l'opcode doivent être 011 et G doit être 2; rien d'autre ne compte. Si c'est le cas, la sortie nommée RORRORA deviendra vraie. Tous les opcodes ROR commencent par 011; mais il existe également d'autres instructions qui commencent par 011. Ceux-ci doivent probablement être filtrés par l'unité "logique de contrôle aléatoire".
Donc, fondamentalement, les opcodes ont été choisis de sorte que les instructions qui devaient faire la même chose les unes que les autres aient quelque chose en commun dans leur modèle de bits. Vous pouvez le voir en regardant une table d'opcode ; toutes les instructions OR commencent par 000, toutes les instructions Store commencent par 010, toutes les instructions qui utilisent l'adressage page zéro sont de la forme xxxx01xx. Bien sûr, certaines instructions ne semblent pas "correspondre", car le but n'est pas d'avoir un format d'opcode complètement régulier mais plutôt de fournir un ensemble d'instructions puissant. Et c'est pourquoi la "logique de contrôle aléatoire" était nécessaire.
La page que j'ai mentionnée ci-dessus dit que certaines des lignes de sortie dans la ROM apparaissent deux fois, "Nous supposons que cela a été fait parce qu'ils n'avaient aucun moyen d'acheminer la sortie d'une ligne où ils voulaient, alors ils ont mis la même ligne à un autre emplacement à nouveau. " Je peux simplement imaginer les ingénieurs dessiner à la main ces portes une par une et réaliser soudainement une faille dans la conception et essayer de trouver un moyen d'éviter de redémarrer tout le processus.
la source
Cela dépend de l'âge de l'ISA.
Au début de la conception manuelle, et plus encore lorsque les CPU étaient assemblés à partir d'une logique discrète, la conception logique serait venue en premier et aurait été considérablement minimisée, puis les modèles de bits ISA auraient été toutes les valeurs requises pour rendre ce minimum travail logique.
Il peut donc y avoir un modèle particulier de signaux de contrôle qui permet à certains multiplexeurs de connecter la sortie ALU à l'entrée du fichier de registre GP, quelques signaux de contrôle supplémentaires qui demandent à l'ALU d'ajouter, de soustraire, ET, OU etc., et quelques-uns adresse les bits dans le fichier de registre. Ces trois groupes de signaux formeront des champs dans l'instruction. Chaque groupe sera maintenu ensemble, et leur signification détaillée découle de la conception de cette unité (ALU, etc.), mais les groupes peuvent être dans n'importe quel ordre, jusqu'à ce que vous conceviez le décodeur d'instructions. (le x86 est assez vieux pour que vous puissiez en détecter une partie si vous regardez au bon endroit - ce n'était pas un design totalement nouveau, mais il s'inspirait de l'ancien 8080)
Les ISA ultérieurs peuvent être «nettoyés» et rendus plus réguliers et plus simples à utiliser, avec du matériel à traduire entre eux et les signaux de contrôle de niveau matériel réels, parfois via un «microcode». Ils sont appelés "CISC" ou "Complex Instruction Set Coding". Le préfixe d'instruction x86 "Rep" en est un exemple simple - il provoque la répétition de l'instruction suivante un certain nombre de fois, pour éviter d'avoir à écrire une boucle FOR.
Plus tard encore (dans les années 1980) est revenu un mouvement vers un style plus simple d'encodage direct (RISC - Reduced Instruction Set Coding) que vous pouvez voir dans les processeurs ARM. Cela était dû à la petite taille des ASIC à l'époque, et au désir de leur mettre des processeurs 32 bits, donc il n'y avait pas de capacité disponible pour les décodeurs de jeux d'instructions complexes, pour réduire le processeur complet à environ 20000 portes. (Il y a également eu une augmentation temporaire des performances, car les gens n'avaient pas encore développé de techniques pour rendre les décodeurs CISC rapides - cela est arrivé vers 1995 avec le Pentium Pro)
Et de nos jours, cela n'a plus d'importance - les processeurs lisent plusieurs instructions à la fois et consacrent des millions de transistors à les décoder, à les réorganiser et à en exécuter autant que possible à la fois, pour accélérer les programmes qui peuvent avoir été écrits pour les plus anciens. style d'ISA.
la source
Si vous regroupez des instructions similaires, des modèles apparaîtront. Ceci est très évident dans ARM, où le manuel ISA vous montre en fait quel bit d'un mot d'instruction correspond à la fonction, au choix de registre, etc. Mais il peut également être déduit pour X86 .
En fin de compte, la partie "fonction" des opcodes va dans un décodeur binaire à un instantané qui active réellement une fonction ou une séquence particulière d'opérations en pipeline. Ils ne sont généralement pas liés au contenu d'une machine d'état, sauf si nous considérons des instructions de longueur variable qui nécessitent une machine d'état pour décoder.
la source
Quelqu'un à un moment donné s'est assis et les a définis.
Un bon ISA rendra le décodeur aussi simple que possible.
Par exemple, avec une instruction ALU, vous pouvez laisser certains bits de l'opcode être envoyés directement dans les lignes de contrôle de l'ALU.
la source
En règle générale, vous divisez votre ISA en groupes fonctionnels. Il est logique (que ce soit pour l'optimisation logique ou simplement pour être bien rangé) que les paires complémentaires soient différenciées par un changement de bit unique (charge vs magasin), et que vous avez une hiérarchie de bits qui affecte l'arbre de décision de décodage.
À la fin de la journée, une allocation arbitraire de bits pour le bloc fonction (au lieu de placer les champs «données» dans l'instruction n'aura qu'un faible impact sur l'efficacité globale de votre conception - mais vous avez beaucoup de choix sur la façon de «optimisez» votre encodage ISA en fonction de ce que vous jugez être un paramètre important.
la source
L'encodage d'instructions est un compromis laid entre.
Pour simplifier le décodage, vous voulez pour cela un ensemble simple de champs dont chacun peut être décodé séparément et routé vers une partie distincte du moteur d'exécution.
Emballage autant de fonctionnalités que possible dans une taille limitée de mot d'instruction. Cela conduit à des choses comme des formats constants spéciaux qui peuvent coder une variété de nombres communs.
Compatibilité ascendante et descendante. Si vous attribuez des fonctionnalités à chaque opcode possible, vous ne vous donnez pas de place pour étendre l'architecture ultérieurement. Si vous ajoutez à une architecture existante, vous devez insérer vos nouvelles instructions dans les opcodes de rechange.
la source
L'excellent (quoique quelque peu daté) de Randy Hyde Art of Assembly va dans le jeu d'instructions x86 en détail dans le chapitre 3.3.4 L'unité de contrôle et les jeux d'instructions et suivants.
Il montre ensuite de façon assez accrocheuse et détaillée comment les deux premiers plugs représentent l'instruction, les plugs suivants encodent la source et la destination. Bien sûr, aujourd'hui, plus personne ne "branche", mais pour les très anciens ISA, les bits de l'opcode font essentiellement le même travail que les fiches précédentes.
Vous vous retrouvez avec quelque chose comme ça:
la source