web-dev-qa-db-ja.com

ARM PCレジスタは、次に実行される命令の後の命令を指すのはなぜですか?

ARM IC。

ARM=状態では、PCの値は現在の命令のアドレス+ 8バイトです。

Thumb状態:

  • B、BL、CBNZ、およびCBZ命令の場合、PCの値は、現在の命令のアドレスに4バイトを加えたものです。
  • ラベルを使用する他のすべての命令の場合、PCの値は現在の命令のアドレスに4バイトを加えたもので、結果のビット[1]は0にクリアされてワード境界になります。

簡単に言うと、PCレジスタの値は次の命令の次の命令を指しています。これは私には得られないものです。通常(特にx86では)プログラムカウンターレジスタは、次に実行される命令のアドレスを指すために使用されます。

それで、その根底にある前提は何ですか?多分条件付き実行?

39
newbie

これは、レガシーな抽象化リークの厄介なビットです。

元のARMデザインには3ステージのパイプライン(フェッチ-デコード-実行)がありました。デザインを簡素化するために、PCを現在の命令フェッチアドレスラインにある値として読み取るようにしました。 2サイクル前に現在実行中の命令よりも多くのPC相対アドレスがリンク時に計算されるため、すべてのロジックを設計して修正するよりも、アセンブラ/リンカーがその2命令オフセットを補正する方が簡単です。 PCレジスタ。

もちろん、それはすべて「30年前に理にかなっていたこと」の山にしっかりと備わっています。今日の15以上のステージ、複数の問題、順不同のパイプラインでそのレジスターに意味のある値を維持するために何が必要かを想像してみてください。PCを公開していると考える最近のCPUデザイナーを見つけるのが難しい理由を理解するかもしれません。レジスターは良い考えです。

それでも、少なくとも、 遅延スロット ほど恐ろしいことではありません。代わりに、あなたが想定していることとは逆に、すべての命令を条件付きで実行することは、実際にはそのプリフェッチオフセットに関するもう1つの最適化でした。条件付きコードの周りを分岐する(または、まだクレイジーな人のようにパイプに残っているものを実行する)ときに常にパイプラインフラッシュの遅延をとる必要はなく、非常に短い分岐を完全に回避できます。パイプラインはビジーのままであり、フラグが一致しない場合、デコードされた命令はNOPとしてのみ実行できます*。繰り返しになりますが、最近では効果的な分岐予測子があり、ヘルプよりも障害の方が多くなっていますが、1985年はクールでした。

* "...地球上で最もNOPが多い命令セット。"

60
Notlikethat

それは本当だ...

以下に1つの例を示します。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;
}

アセンブリにコンパイル:

    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

上記のLDRのPC値を参照してください。ここでは、変数f、g、yのアドレスをr3にロードするために使用されます。

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

PCの値は、現在実行中の命令の次の次の命令にすぎません。 as ARMは32ビット命令を使用しますが、バイトアドレスを使用しているため、+ 8は8バイト、2つの命令の長さを意味します。

そのように添付ARM archiの5ステージパイプラインフェッチ、デコード、実行、メモリ、ライトバック

ARMの5ステージパイプライン

pCレジスタは各クロックで4ずつ追加されるため、命令が実行のためにバブリングされると、現在の命令では、PCレジスタのすでに2クロックが経過します。今では+ 8です。つまり、PCは「フェッチ」命令を指し、現在の命令は「実行」命令を意味するため、PCは次に実行されるものを意味します。

ところで:写真はデジタルデザインとコンピューターアーキテクチャのハリスの本からですARM Edition

2
Harry