Je suis nouveau dans Langue de l’Assemblée . Je lisais à propos deMIPSarchitecture et je suis coincé avec Adresse cible de saut et Adresse cible de branche et comment calculer chacun d'entre eux.
Dans la branche MIPS, l'instruction n'a que 16 bits décalés pour déterminer la prochaine instruction. Nous avons besoin d'un registre ajouté à cette valeur de 16 bits pour déterminer la prochaine instruction et ce registre est en réalité impliqué par l'architecture. Il s’agit d’un registre de PC puisque le PC est mis à jour (PC + 4) pendant le cycle de récupération, de sorte qu’il conserve l’adresse de l’instruction suivante.
(Dans les diagrammes ci-dessous, PC
est l'adresse du créneau de délai de branchement, pas l'instruction de branche elle-même. Mais dans le texte, nous dirons PC + 4.)
Nous limitons également la distance de branche à l'instruction -2^15 to +2^15 - 1
à partir de l'instruction (instruction après l'instruction). Cependant, ce n’est pas un réel problème puisque la plupart des agences sont de toute façon locales.
Donc, étape par étape:
Pour l'instruction de saut, Mips n'a que 26 bits pour déterminer l'emplacement du saut. En outre, les sauts sont relatifs au PC dans MIPS. Comme pour les branches, la valeur de saut immédiat doit être alignée sur Word, il est donc nécessaire de multiplier une adresse de 26 bits par quatre.
Encore une fois étape par étape:
En d'autres termes, remplacez les 28 bits inférieurs du PC + 4 par les 26 bits inférieurs de l'instruction recherchée décalés à gauche de 2 bits.
Les sauts sont relatifs à la région par rapport au créneau de retard de branche, pas nécessairement à la branche elle-même. Dans le diagramme ci-dessus, le PC est déjà passé au créneau du délai de branchement avant le calcul du saut. (Dans un pipeline à étapes RISC classique-5, le BD a été récupéré dans le même cycle que le saut est décodé, de sorte que l'adresse d'instruction suivante PC + 4 est déjà disponible pour les sauts ainsi que pour les branches, et le calcul relatif à l'adresse propre du saut serait ont demandé un travail supplémentaire pour enregistrer cette adresse.)
Source: Université de Bilkent CS 224 Diapositives du cours
Habituellement, vous n'avez pas à vous soucier de les calculer car votre assembleur (ou votre éditeur de liens) aura besoin d'obtenir les bons calculs. Disons que vous avez une petite fonction:
func:
slti $t0, $a0, 2
beq $t0, $zero, cont
ori $v0, $zero, 1
jr $ra
cont:
...
jal func
...
Lors de la traduction du code ci-dessus en un flux d'instructions binaire, l'assembleur (ou l'éditeur de liens si vous l'avez assemblé dans un fichier objet) détermine l'emplacement de la fonction en mémoire (ignorons le code indépendant de la position pour l'instant). L’emplacement où il réside en mémoire est généralement spécifié dans l’ABI ou vous est donné si vous utilisez un simulateur (comme SPIM qui charge le code sur 0x400000
- notez le lien. contient également une bonne explication du processus).
En supposant que nous parlions du cas SPIM et que notre fonction soit la première en mémoire, l'instruction slti
résidera à 0x400000
, la beq
à 0x400004
et ainsi de suite. Maintenant nous y sommes presque! Pour l'instruction beq
, l'adresse cible branch est celle de cont
(0x400010
) en regardant un référence d'instruction MIPS , elle est codée comme une signature immédiate de 16 bits par rapport à l'instruction suivante ( divisé par 4 car toutes les instructions doivent de toute façon résider sur une adresse alignée sur 4 octets).
C'est:
Current address of instruction + 4 = 0x400004 + 4 = 0x400008
Branch target = 0x400010
Difference = 0x400010 - 0x400008 = 0x8
To encode = Difference / 4 = 0x8 / 4 = 0x2 = 0b10
Encodage de beq $t0, $zero, cont
0001 00ss ssst tttt iiii iiii iiii iiii
---------------------------------------
0001 0001 0000 0000 0000 0000 0000 0010
Comme vous pouvez le constater, vous pouvez vous connecter à -0x1fffc .. 0x20000
octets. Si, pour une raison quelconque, vous devez sauter plus loin, vous pouvez utiliser un trampoline (un saut inconditionnel vers la cible réelle placée dans la limite donnée).
Les adresses de cible Jump, contrairement aux adresses de cible de branche, sont codées à l'aide de l'adresse absolute (à nouveau divisée par 4). Comme le codage de l’instruction utilise 6 bits pour le code opération, il ne reste que 26 bits pour l’adresse (effectivement 28 étant donné que les 2 derniers bits seront 0), les bits les plus significatifs de 4 bits du registre PC sont utilisés lors de la formation de l’adresse ( n’importera pas sauf si vous avez l’intention de franchir les 256 Mo).
Pour revenir à l'exemple ci-dessus, le codage pour jal func
est:
Destination address = absolute address of func = 0x400000
Divided by 4 = 0x400000 / 4 = 0x100000
Lower 26 bits = 0x100000 & 0x03ffffff = 0x100000 = 0b100000000000000000000
0000 11ii iiii iiii iiii iiii iiii iiii
---------------------------------------
0000 1100 0001 0000 0000 0000 0000 0000
Vous pouvez le vérifier rapidement et jouer avec différentes instructions, en utilisant cet assembleur MIPS en ligne i couru (notez que cela ne prend pas en charge tous les opcodes, par exemple slti
, je l'ai donc changé en slt
ici). :
00400000: <func> ; <input:0> func:
00400000: 0000002a ; <input:1> slt $t0, $a0, 2
00400004: 11000002 ; <input:2> beq $t0, $zero, cont
00400008: 34020001 ; <input:3> ori $v0, $zero, 1
0040000c: 03e00008 ; <input:4> jr $ra
00400010: <cont> ; <input:5> cont:
00400010: 0c100000 ; <input:7> jal func
Pour de petites fonctions comme celle-ci, vous pouvez simplement compter à la main le nombre de sauts vers la cible, à partir de l'instruction sous l'instruction de branche. Si elle se ramifie à l’arrière, le nombre de sauts devient négatif. si ce nombre n'exige pas les 16 bits, pour chaque nombre situé à gauche du nombre le plus significatif de votre nombre de sauts, attribuez-leur la valeur 1, si le nombre de sauts est positif, attribuez-leur la valeur 0 cibles, cela vous évite beaucoup d’arithmétique supplémentaire dans la plupart des cas.