pourquoi les architectures CPU utilisent-elles un registre de drapeaux (avantages?)

15

Certains CPU ont un registre de drapeaux (ARM, x86, ...), d'autres non (MIPS, ...). Quel est l'avantage d'avoir une instruction CMP pour mettre à jour le registre des drapeaux suivie d'une instruction de branche au lieu d'utiliser un registre zéro et des branches conditionnelles pour vérifier le signe, le débordement, etc.?

monde modèle
la source

Réponses:

11

Dans les micro-architectures modernes avec registre renommant le coût de mise en œuvre des drapeaux ou non, les drapeaux sont assez similaires. La principale différence à laquelle je peux penser est que certains indicateurs indiquent les caractéristiques d'une valeur (la valeur est-elle négative? La valeur est-elle nulle? La valeur a-t-elle une parité paire ou impaire?), Tandis que d'autres représentent un événement qui s'est produit lors d'une opération précédente (l'instruction add a-t-elle eu une exécution ou un débordement?) Cela a conduit à une situation moins qu'idéale sur le MIPS lorsque vous vouliez simuler un ajout 64 bits sur l'architecture 32 bits (ou un ajout 128 bits sur le Architecture 64 bits.) Sur la plupart des architectures avec un indicateur de portage, il existe unadd-with-carry, qui comprend le drapeau de report de l'instruction d'ajout précédente. Cela rend la simulation de l'arithmétique multi-précision relativement peu coûteuse sur de nombreuses architectures avec des registres de drapeaux.

D'un autre côté, tester un registre à N bits pour zéro ou non nul est en fait étonnamment cher. Pour tester un registre à N bits sur zéro, vous devez effectuer une opération NOR à N bits, qui nécessite des niveaux logiques pour le calcul. Sur les architectures avec des drapeaux, la logique supplémentaire pour le calcul zéro / non nul à la fin de l'étape ALU peut ralentir le temps (ou forcer l'ALU à avoir deux opérations de cycle). Pour cette raison, je pense que certains les architectures, comme SPARC, avaient deux versions de chaque opération arithmétique, une qui définissait des indicateurs et une qui ne le faisait pas.O(JournalN)

Mais MIPS n'enregistre rien ici. Ils ont simplement déplacé le problème ailleurs. Sur MIPS, il y a une branch-on-equalinstruction. Cela signifie que l'instruction de branchement doit en fait avoir un étage ALU (y compris quelque chose comme une xoropération au niveau du bit suivie d'un norpour réduire au bit unique égal / non égal) avant de déterminer dans quelle direction va la branche.

L'architecture DEC Alpha a tenté de diviser la différence en utilisant une astuce. DEC Alpha n'avait aucun registre de drapeaux, mais n'avait pas non plus d' branch-on-equalinstruction. Au lieu de cela, les instructions de branche regardent toutes l'état d'un seul registre à usage général. Il est branch-on-zero, branch-on-not-zero, branch-on-less-than-zero, etc. L'astuce est que vous pouvez donner à chaque registre banalisé un peu de 65e supplémentaire qui vous indique si les autres 64 bits sont tous nuls ou non. Cela ressemble plus à un registre de drapeaux: toutes les instructions de branchement regardent un seul bit (qui est déjà calculé) pour prendre leur décision, mais maintenant vous êtes de retour pour trouver comment calculer ce bit indicateur de zéro supplémentaire pendant une ALU normale cycle. (Et vous ne pouvez toujours pas faire de l'arithmétique multi-précision simplement en regardant l'indicateur de report de l'opération précédente.)

Logique errante
la source
2
Les opérations de paramétrage non CC étaient (d'après ce que je comprends) une optimisation du compilateur , permettant au compilateur de planifier les instructions de paramétrage CC tôt sans que la valeur ne soit assaillie par ces dernières instructions. Le PowerPC750 a placé les registres de conditions (8 registres 4 bits) plus près de l'extrémité avant de sorte qu'une branche prise atteignant le cache d'instructions cible de branche et ayant la condition disponible suffisamment tôt pourrait résoudre une branche prise sans pénalité. (Le CRISP d'AT & T a également exploité la résolution précoce des branches.) La petite quantité et la spécialisation des CC rendent cela plus pratique.
Paul A. Clayton du
Un détail: tous les calculs de drapeaux ne sont pas égaux. Imaginez que votre CPU possède les drapeaux NZVC traditionnels. Si toutes les instructions ALU sont autorisées à mettre à jour les indicateurs, vous devez placer la génération d'indicateurs après l'additionneur / le soustracteur et quelques multiplexeurs. Le drapeau négatif est facile, c'est juste le MSB, tandis que le drapeau zéro est cher et dépend de chaque bit. Maintenant, si vous limitez les indicateurs aux instructions de comparaison (et de test de bits), les indicateurs zéro peuvent être calculés avec des XOR parallèles sur les opérandes source, sans attendre le résultat de la soustraction. Le calcul du drapeau Z après un ajout est presque inutile.
TEMLIB
7

1 Du point de vue ISA

  1. Avoir des instructions de test qui ne définissent que les drapeaux n'est qu'un moyen de réduire la pression de registre dans les architectures de registre affamées. Si vous avez suffisamment de registres, modifiez simplement l'un d'entre eux et ignorez le résultat. L'astuce d'avoir un registre 0 avec une valeur d'entrée 0 est juste une astuce de codage pratique lorsque vous avez suffisamment de registres que la fixation de l'un d'entre eux à 0 est préférable à l'augmentation du nombre d'instructions. Il est alors pratique de l'utiliser également comme cible (cela réduit le nombre de fausses dépendances).

  2. Encodage à nouveau. Si vous encodez la condition en sauts, vous aurez des sauts avec 3 opérandes (les deux à comparer et la cible de saut), dont deux vous aimeriez être des valeurs immédiates, un que vous aimeriez être aussi grand que possible (les sauts ont souvent leur propre format de codage afin que la cible puisse utiliser autant de bits que possible). Ou vous laissez tomber les possibilités.

  3. L'utilisation de drapeaux vous donne plus d'occasions de les définir. Ce ne sont pas seulement les opérations de comparaison qui peuvent définir les indicateurs, mais tout ce que vous voulez. (Avec la mise en garde que plus vous avez d'opérations qui définissent des indicateurs, plus vous devez vous assurer que la dernière opération qui a défini les indicateurs est celle que vous voulez). Si vous avez des drapeaux, vous pouvez tester le nombre de conditions (souvent 16) multiplié par le nombre d'instructions qui sont en mesure de définir les drapeaux (si vous n'utilisez pas de drapeaux, vous vous retrouvez avec autant de sauts conditionnels que vous avoir des choses à tester ou il y a des choses que vous ne permettez pas de tester aussi facilement (transporter ou déborder par exemple).

2 Du point de vue du réalisateur

  1. Le test des drapeaux est facile et peut être fait rapidement. Plus votre test est complexe, plus il aura d'effet sur la durée du cycle (ou la structure du pipeline si vous êtes pipeliné). Cela est particulièrement vrai pour les implémentations plus simples, lorsque vous arrivez à un processeur haut de gamme utilisant toutes les astuces du livre, l'effet est assez minime.

  2. Avoir des drapeaux signifie que beaucoup d'instructions ont plusieurs résultats (le résultat naturel et chacun des drapeaux modifiés). Et à partir d'un PDV de micro-architecture, plusieurs résultats sont mauvais (vous devez garder une trace de leur association). Lorsque vous n'avez qu'un seul ensemble d'indicateurs, qui introduisent des dépendances (inutiles si l'indicateur n'est pas utilisé ensuite), vous devez gérer d'une manière ou d'une autre. Encore une fois, cela est particulièrement vrai pour les implémentations plus simples, lorsque vous arrivez à un processeur haut de gamme en utilisant toutes les astuces du livre, les difficultés supplémentaires sont éclipsées par le reste du processeur.

AProgrammer
la source
2

Sur une machine 32 bits, une instruction "ajouter avec porter" utilisée dans le cadre d'une séquence d'addition multi-précision doit accepter une valeur d'opérandes de 65 bits et calculer une somme de 33 bits. Les spécifications du registre source identifieront d'où les 64 bits d'opérande devraient provenir, et la spécification du registre de destination dira où les 32 bits inférieurs du résultat devraient aller, mais que faire de l'opérande "ajouter un supplémentaire" ou du bit supérieur du résultat? Être autorisé à spécifier dans le cadre de l'instruction d'où l'opérande supplémentaire devrait provenir et où le bit de résultat supplémentaire devrait aller serait modérément utile, mais il ne serait généralement pas assez utile pour justifier un champ supplémentaire dans l'opcode. Avoir un «emplacement» fixe pour gérer le drapeau de transport peut être un peu gênant du point de vue de la programmation des instructions, mais c'est

Si l'on essayait de concevoir un jeu d'instructions pour permettre l'arithmétique multi-précision mais que chaque instruction était limitée à deux opérandes 32 bits et un opérande de destination 32 bits, on pourrait implémenter un "add" 64 bits dans quatre instructions: "set r5 à 1 si r0 + r2 porterait ou zéro sinon; calculer r4 = r1 + r3; calculer r5 = r4 + r5; calculer r4 = r0 + r2 ", mais pour aller au-delà, il faudrait trois instructions pour chaque mot supplémentaire. Avoir un indicateur de portage disponible comme source et destination supplémentaire réduit le coût à une instruction par mot.

Notez, btw, que le fait d'avoir un bit d'instruction contrôlant si l'instruction met à jour le registre d'indicateur peut faciliter l'exécution dans le désordre, car les instructions qui utilisent ou modifient les bits d'indicateur doivent conserver leur séquence les unes par rapport aux autres, mais les instructions qui ne le font pas non plus peuvent être réarrangé librement. Étant donné la séquence:

ldr  r0,[r1]
add  r0,r0,r2
eors r4,r5,r6

une unité d'exécution pourrait assez facilement reconnaître que la troisième instruction pourrait s'exécuter sans avoir à attendre que les données soient lues [r1], mais si la deuxième instruction l'avait été, adds r0,r0,r2cela ne serait possible que si l'unité d'exécution pouvait s'assurer qu'au moment où quelque chose essayait d'utiliser les drapeaux, le drapeau zéro contiendrait la valeur établie dans la troisième instruction mais le drapeau de retenue conserverait la valeur dans la seconde.

supercat
la source
1
"bit d'instruction contrôle si l'instruction met à jour le registre des indicateurs": disponible par exemple dans PowerPC, SPARC.
TEMLIB
MIPS utilise "r5 = r1 + r2; définissez r6 si r6 est inférieur à r1; r7 = r3 + r4; r5 = R5 + R6;". Certaines extensions SIMD pourraient utiliser des comparaisons qui mettent tous les bits à zéro ou à un (c.-à-d. Zéro ou -1 deux entiers complémentaires) pour trouver le report et la soustraction pour appliquer le report.
Paul A. Clayton
@ PaulA.Clayton: Je pense que vous vouliez dire "si r5 est inférieur à r1". Comment MIPS gérerait-il des mathématiques plus longues? Cela exigerait-il trois, plus de trois ou moins de trois instructions par mot?
supercat
@supercat Ouais, cela aurait dû être "défini r6 si r5 est inférieur à r1"!
Paul A. Clayton
@ PaulA.Clayton: Comment procéder pour ajouter, par exemple, deux nombres de 64 mots (2048 bits) sur un MIPS 32 bits? Existe-t-il un moyen efficace de gérer les portées dans et hors des étapes intermédiaires?
supercat
0

Réponse simple ... opération de mémoire rapide et bon marché qui ne nécessite absolument aucune utilisation de bus interne, sauf l'instruction elle-même. Il peut être utilisé comme une pile booléenne sans pile ni bit de processus, sans mémoire.

SkipBerne
la source
1
Cette réponse est plutôt légère sur les détails. Des réponses longues ne sont pas nécessairement nécessaires, mais quelque chose de plus étoffé serait une nette amélioration.
David Richerby
définir un indicateur ou comparer une valeur d'indicateur est une instruction unique sans aucune autre information sous la forme d'arguments qui seraient inclus dans le code d'assembly. Les drapeaux sont également le résultat du fonctionnement ou du test d'un processeur et peuvent être utilisés efficacement pour se ramifier. ils sont le bit réel qui est basculé ou défini lorsque deux valeurs sont comparées dans les registres.
SkipBerne