web-dev-qa-db-fra.com

Pourquoi le registre ARM PC pointe-t-il sur l'instruction à exécuter après la suivante?

Selon le ARM IC.

Dans l'état ARM, la valeur du PC est l'adresse de l'instruction en cours plus 8 octets.

Dans l'état Thumb:

  • Pour les instructions B, BL, CBNZ et CBZ, la valeur du PC est l'adresse de l'instruction en cours plus 4 octets.
  • Pour toutes les autres instructions qui utilisent des étiquettes, la valeur du PC est l'adresse de l'instruction en cours plus 4 octets, avec le bit [1] du résultat effacé à 0 pour le rendre aligné sur Word.

Autrement dit, la valeur du registre PC pointe vers l'instruction après l'instruction suivante. C'est la chose que je ne comprends pas. Habituellement (en particulier sur le x86), le registre de compteur de programme est utilisé pour pointer vers l'adresse de la prochaine instruction à exécuter.

Alors, quels sont les prémisses qui sous-tendent cela? Exécution conditionnelle, peut-être?

39
newbie

C'est un peu méchant de fuite d'abstraction héritée.

La conception originale ARM avait un pipeline en 3 étapes (fetch-decode-execute). Pour simplifier la conception, ils ont choisi de faire lire le PC comme la valeur actuellement sur les lignes d'adresse de récupération des instructions, plutôt que celle de l'instruction en cours d'exécution d'il y a 2 cycles. Comme la plupart des adresses relatives au PC sont calculées au moment de la liaison, il est plus facile pour l'assembleur/éditeur de liens de compenser ce décalage de 2 instructions que de concevoir toute la logique pour "corriger" la Registre PC.

Bien sûr, tout est fermement sur la pile des "choses qui avaient du sens il y a 30 ans". Imaginez maintenant ce qu'il faut pour conserver une valeur significative dans ce registre sur les pipelines actuels à plus de 15 étapes et en panne, et vous comprendrez peut-être pourquoi il est difficile de trouver un concepteur de processeur de nos jours qui pense exposer le PC comme un registre est une bonne idée.

Pourtant, à la hausse, au moins ce n'est pas aussi horrible que slots de retard . Au lieu de cela, contrairement à ce que vous supposez, l'exécution de chaque instruction de manière conditionnelle n'était en réalité qu'une autre optimisation autour de ce décalage de prélecture. Plutôt que de toujours avoir à prendre des retards de vidage de pipeline lors de la ramification autour du code conditionnel (ou encore d'exécuter tout ce qui reste dans le tuyau comme un fou), vous pouvez éviter complètement les branches très courtes; le pipeline reste occupé et les instructions décodées peuvent simplement s'exécuter en tant que NOP lorsque les drapeaux ne correspondent pas*. Encore une fois, ces jours-ci, nous avons des prédicteurs de branche efficaces et cela finit par être plus un obstacle qu'une aide, mais pour 1985, c'était cool.

* "... l'ensemble d'instructions avec le plus de NOP de la planète."

60
Notlikethat

c'est vrai...

un exemple est ci-dessous: Programme C:

int f,g,y;//global variables
int sum(int a, int b){
     return (a+b);
}
int main(void){
    f = 2;
    g = 3;
    y = sum(f, g);
    return y;
}

compiler vers l'assembly:

    00008390 <sum>:
int sum(int a, int b) {
return (a + b);
}
    8390: e0800001 add r0, r0, r1
    8394: e12fff1e bx lr
    00008398 <main>:
int f, g, y; // global variables
int sum(int a, int b);
int main(void) {
    8398: e92d4008 Push {r3, lr}
f = 2;
    839c: e3a00002 mov r0, #2
    83a0: e59f301c ldr r3, [pc, #28] ; 83c4 <main+0x2c> 
    83a4: e5830000 str r0, [r3]
g = 3;
    83a8: e3a01003 mov r1, #3
    83ac: e59f3014 ldr r3, [pc, #20] ; 83c8 <main+0x30>
    83b0: e5831000 str r1, [r3]
y = sum(f,g);
    83b4: ebfffff5 bl 8390 <sum>
    83b8: e59f300c ldr r3, [pc, #12] ; 83cc <main+0x34>
    83bc: e5830000 str r0, [r3]
return y;
}
83c0: e8bd8008 pop {r3, pc}
83c4: 00010570 .Word 0x00010570
83c8: 00010574 .Word 0x00010574
83cc: 00010578 .Word 0x00010578

voir la valeur PC du LDR ci-dessus - ici est utilisée pour charger l'adresse de la variable f, g, y dans r3.

    83a0: e59f301c ldr r3, [pc, #28];83c4 main+0x2c
    PC=0x83c4-28=0x83a8-0x1C = 0x83a8

La valeur du PC est juste la prochaine instruction de l'instruction d'exécution actuelle. as ARM utilise l'instruction 32bits, mais il utilise l'adresse octet, donc + 8 signifie 8 octets, la longueur de deux instructions.

donc attaché ARM archi pipe pipe linefetch, decode, execute, memory, writeback

pipeline en 5 étapes d'ARM

le registre PC est ajouté par 4 chaque horloge, donc lorsque l'instruction bouillonne pour s'exécuter - l'instruction actuelle, l'horloge du registre PC est déjà passée 2! maintenant c'est + 8. cela signifie en fait: PC pointe l'instruction "fetch", l'instruction courante signifie l'instruction "execute", donc PC signifie la prochaine suivante à exécuter.

BTW: la photo provient du livre de Harris sur la conception numérique et l'architecture informatique ARM Edition

2
Harry