Pourquoi MIPS a-t-il inclus shamt et distingué funct / opcode?

15

Je ne comprends pas pourquoi les concepteurs de MIPS incluraient 5 bits dédiés au décalage et auraient des bits d'opcode et de fonction séparés.

Parce que MIPS est tellement RISC, je suppose que seul le décalage serait effectué en quelques instructions, donc ces 5 bits semblent gaspiller de l'espace lorsqu'ils pourraient être mis dans l'immédiat. Je suppose que les opcodes et funct sont séparés pour distinguer les instructions de type R et I, mais cela pourrait être fait en étendant l'opcode d'un bit. Avec ces deux instructions de type R, la longueur pourrait être de 22 bits. Cela ne fonctionnera pas si les instructions de type I et de type J veulent conserver leur adresse immédiate et leur adresse, mais les deux semblent inutiles.

qwr
la source

Réponses:

10

Il y a quelques compromis différents à faire ici.

Tout d'abord, nous voulons que les instructions soient à largeur fixe (32 bits). Cela garantit que les instructions sont mises en cache et alignées sur la page, ce qui simplifie la présence de cache et de page et les vérifications d'autorisation.

Deuxièmement, nous voulons que les différents champs d'instructions ( opcode/ source regs/ immediates) soient à largeur et position fixes. Cela les rend plus rapides / moins logiques à décoder et ils sont nécessaires dans les premières étapes du pipeline. (Le destinationregistre n'est pas nécessaire jusqu'à la fin du pipeline, il peut donc être à différents endroits Ret Iinstructions.) La position et la largeur du functionchamp importent un peu moins car cela doit contrôler la fonction de l'ALU, mais c'est dans la troisième phase du pipeline, vous avez donc un peu de temps pour travailler avec elle si nécessaire.

IJJ228228Iles instructions sont également agréables pour les rédacteurs de compilateurs / éditeurs de liens. (Sur le SPARC, où le champ immédiat n'était que de 12 bits, ils ont dû ajouter une load-highclasse d'instruction spéciale entière avec un 20 bits immédiat.)

26=64JRI

Mais cela laisse une marge de manœuvre avec les Rinstructions. Mis à part l'opcode 6 bits, ceux-ci n'ont besoin que de 15 bits supplémentaires pour la spécification du registre, ce qui laisse 11 bits pour l'opcode étendu et / ou la quantité de décalage.

Vous devez considérer le functionchamp comme un opcode étendu pour l' Rinstruction. Il n'y a qu'un seul Ropcode d'instruction, mais il y en a 64 différentes functionsque l' Rinstruction peut exécuter.

D'accord. Nous avons 60 Iinstructions différentes et 64 Rinstructions différentes , alors où devrions-nous mettre les instructions de changement immédiat?

Eh bien, non seulement il y a moins d' Iinstructions, mais il y a beaucoup plus de choses que nous voulons faire avec les I instructions. Rappelez-vous que toutes les instructions de branchement doivent être des Iinstructions car elles ont un décalage relatif (immédiat). Toutes les instructions de chargement et de stockage sont également Iformatées sur MIPS. Et enfin, nous avons besoin que l'instruction load-upper-immediate soit une Iinstruction. Non seulement cela, mais les Rinstructions ont encore 5 bits supplémentaires inutilisés, (ce dont nous avons besoin pour l'immédiat d'un décalage immédiat sur cette architecture), donc cela incite davantage à faire des décalages immédiats en Rinstructions spéciales (étranges) .

Beaucoup de ces décisions sont plus de l'art que de la science, mais il existe une logique sous-jacente qui peut être discernée. L'objectif clé est pas de faire le nombre d'instructions aussi petit que possible, il est de faire une haute performancepipeline installé sur une seule puce (de sorte que de petites entreprises, comme MIPS et Sun dans les années 1980, pouvaient concurrencer IBM et DEC). (Le nom RISC, inventé par David Patterson, est quelque peu malheureux. Il a fait son chemin parce qu'il était mignon, non pas parce que "instructions réduites" est une description précise de ce que les architectures MIPS et SPARC essayaient vraiment de faire.) Donc, vous voulez que le instructions largeur fixe (et relativement petite pour que vous obteniez un meilleur comportement I-cache) pour rendre la récupération, la pagination et le décodage plus simples et plus rapides. Vous voulez que les parties de l'instruction qui doivent être décodées tôt (leopcode, les deux registres source et le signe étendu immédiatement) doivent avoir une largeur fixe et une position fixe. Vous voulez que les intermédiaires soient aussi longs que possible et vous voulez autant de types d'instructions différents que possible, compte tenu de toutes ces autres contraintes.

Logique errante
la source
Merci pour votre réponse informative, en particulier la partie sur les objectifs des concepteurs d'architecture. Je trouve intéressant de comparer MIPS au MOS 6502, car si je le comprends bien, le 6502 n'a jamais eu honte (j'essaie toujours de comprendre les formats d'instructions).
qwr
1
Le 6502 était une conception de microprocesseur de première génération (pré-CISC), même s'il prévoyait un pipeline, en ce sens qu'il pouvait enregistrer la réécriture en même temps qu'il chargeait l'instruction suivante. Le 6502 avait des opcodes octets, comme la plupart des micros 8 bits. Une autre architecture à considérer est l'ARM, qui a été conçu par un groupe d'ingénieurs en électronique de haut niveau qui a lu les documents RISC de Berkeley et a visité l'usine MOS et a décidé "hé, nous pouvons le faire".
Pseudonyme du
Je me demande quelles auraient été les implications s'il y avait un modèle de bits fictifs qui signifiait "ne pas exécuter l'instruction suivante, mais utiliser les 32 bits qui ont été récupérés pour cela comme l'opérande source de cette instruction"? Alternativement ou en plus, je me demande s'il aurait été pratique d'avoir un morceau d'espace d'opcode juste dédié à des paires d'instructions simples sans interruption - un concept un peu comme Thumb, mais librement intercalable avec des instructions 32 bits, et sans la possibilité de passer directement à la deuxième instruction d'un mot?
supercat
5

Pour comprendre les formats d'instructions MIPS I, vous devez comprendre le pipeline MIPS et repenser à la technologie d'implémentation du processeur vers 1985. Si vous regardez le diagramme (vous connaissez celui-ci), vous verrez que la lecture du fichier de registre se trouve dans le Étape d'identification, juste après IF.

Aux fins d'une instruction de type R, l'étape ID doit effectuer les tâches suivantes:

  1. Déterminez qu'il s'agit en fait d' une instruction de type R.
  2. Si c'est le cas, indiquez au fichier de registre de charger les valeurs à partir des registres.

Aux fins de cette discussion, c'est la première tâche à laquelle vous devez penser. S'il y a beaucoup de travail de décodage d'instructions que vous devez faire pour même déterminer si vous avez besoin de valeurs de registres, cela augmente le délai avant de pouvoir démarrer les lectures de registre. Cela augmente également la complexité de l'étape d'identification. En réservant un seul opcode pour toutes les instructions de type R, vous gardez la complexité au minimum.

Il semble un peu étrange que vous consacriez cinq bits uniquement au décalage. Je peux penser à quelques explications possibles. La première est qu'elle simplifie le routage (ces cinq bits sont TOUJOURS introduits directement dans le fichier de registre, ces cinq bits sont TOUJOURS introduits dans le barillet, ces six bits sont TOUJOURS acheminés vers l'ALU pour déterminer la fonction à exécuter).

Ils ont peut-être pensé à introduire à l'avenir des instructions combinées de décalage vers la gauche et d'ajout. Ce serait probablement sous la forme:

$d = $s + ($t << shamt)

2s+1s

Aujourd'hui, nous ne penserions probablement pas à deux fois à avoir une étape de décodage plus complexe, d'autant plus que les accès aux fichiers de registre ont tendance à se produire plus tard dans le pipeline d'un processeur superscalaire typique. De nombreux processeurs modernes effectuent même un décodage d'instructions grossières au moment où une instruction est insérée dans le cache L1 . Vous agrandissez les lignes I-cache de quelques bits pour stocker les informations supplémentaires (grâce à la loi de Moore, vous avez beaucoup de transistors à perdre) pour rendre le décodage des instructions "correct" plus simple et plus rapide.

Une des raisons pour lesquelles ils voulaient probablement garder le champ opcode aussi petit que possible est afin qu'il ne pénalise pas indûment les instructions de type J. Comme vous le savez probablement, les instructions de type J utilisent un adressage pseudo-direct. Pour le bénéfice de tous ceux qui jouent à la maison, je vais l'expliquer brièvement.

Le champ d'adresse d'une instruction de type J est de 26 bits. Comme les instructions sont toujours alignées sur 4 octets, vous n'avez pas besoin de stocker les deux bits les moins significatifs, ce qui signifie que vous avez effectivement 28 bits d'adresse. Cependant, l'espace d'adressage dans MIPS I est de 32 bits. Ainsi, les quatre premiers bits de l'emplacement de saut sont extraits du compteur de programmes.

Cela signifie que vous ne pouvez pas accéder directement à un emplacement où les quatre bits les plus significatifs de l'emplacement du PC sont différents. Vous devriez plutôt effectuer un saut à trois instructions plus cher dans un registre à gratter:

lui $r,target >> 16
    ori $r,$r,target & 0xFFFF
    jr $r

Ce n'est pas trop mal aujourd'hui, mais en 1985, c'est beaucoup de cycles d'horloge.

Voler un peu du champ d'adresse réduirait encore plus la portée effective d'un saut direct. Vous pouvez voir comment cela pourrait être un prix trop élevé à payer.

Pseudonyme
la source
"instructions combinées de décalage vers la gauche et d'ajout" du type vu plus tard dans ARM?
Damian Yerrick