6.3.3. 復帰アドレスと復帰命令

例外発生時にプログラムカウンタが指す実際の位置は、例外タイプによって異なります。復帰アドレスは、必ずしもプログラムカウンタが指す次の命令であるとは限りません。

例外が ARM 状態で発生した場合、プロセッサは(PC - 4)を lr_ mode に格納します。しかし、例外が Thumb 状態で発生した場合は、例外タイプごとに異なる値がプロセッサによって自動的に格納されます。このような調整が必要な理由は、Thumb 命令が ARM 命令のようにフルワードではなく、ハーフワードしか使用しないためです。

この調整がプロセッサによって行われないとすると、ハンドラはプロセッサの元の状態を判別し、ARM コードではなく Thumb コードに戻るために異なる命令を使用する必要があります。しかしプロセッサがこの調整を行うことによって、ハンドラは例外発生時のプロセッサ状態(ARM または Thumb)に関係なく、1 つの復帰命令で正しく復帰できます。

これ以降のセクションでは、各タイプの例外を処理するコードから正しく復帰するための命令について説明します。

SVC ハンドラおよび未定義命令ハンドラからの復帰

SVC 例外と未定義命令例外は、命令自身によって生成されるため、これらの例外が発生してもプログラムカウンタは更新されません。プロセッサは(pc - 4)を lr_ mode に格納します。これにより、lr_mode は次に実行される命令を指します。以下の命令を使用してリンクレジスタからプログラムカウンタを復元すると、

    MOVS        pc, lr

ハンドラから制御が戻されます。

以下は、復帰アドレスをスタックにプッシュし、復帰時にそれをポップするハンドラのエントリ/終了コードを示しています。

    STMFD        sp!,{reglist,lr}
    ;...
    LDMFD        sp!,{reglist,pc}^

Thumb 状態で例外が発生する場合を除き、このハンドラの復帰命令(MOVS pc,lr)によって、プログラムカウンタは次に実行する命令のアドレスに変更されます。このアドレスの値は(pc - 2)にあるため、プロセッサが lr_mode に格納する値は(pc - 2)となります。

FIQ ハンドラおよび IRQ ハンドラからの復帰

各命令の実行後、プロセッサは割り込みピンが LOW にセットされ、CPSR 内の割り込みディセーブルビットがクリアされていることをチェックします。この結果、プログラムカウンタが更新されている場合にのみ IRQ 例外または FIQ 例外が生成されます。プロセッサは(pc - 4)を lr_mode に格納します。これにより lr_mode は、例外が発生した命令の終わりから 1 つ先の命令を指します。ハンドラ終了後、lr_mode が指す命令の前の命令から実行が継続される必要があります。実行が再開されるアドレスは、lr_mode の値よりも 1 ワード(4 バイト)少ない値であるため、復帰命令は以下のようになります。

    SUBS        pc, lr, #4

以下は、復帰アドレスをスタックにプッシュし、復帰時にそれをポップするハンドラのエントリ/終了コードを示しています。

    SUB        lr,lr,#4
    STMFD      sp!,{reglist,lr}
    ;...
    LDMFD        sp!,{reglist,pc}^

Thumb 状態で例外が発生する場合を除き、このハンドラの復帰命令(SUBS pc,lr,#4)によって、プログラムカウンタは次に実行する命令のアドレスに変更されます。プログラムカウンタは例外発生前に更新されるため、次の命令の位置は(pc - 4)となります。したがって、プロセッサが lr_mode に格納する値は pc となります。

プリフェッチアボートハンドラからの復帰

プロセッサが不正アドレスから命令をフェッチしようとすると、その命令に無効のフラグが立てられます。パイプラインに既に入っている命令の実行は、その無効な命令に到達するまで継続され、無効な命令に到達した時点でプリフェッチアボートが生成されます。

この例外ハンドラは、マップされていない命令を物理メモリにロードし、MMU があればこれを使用して、その仮想メモリの位置を物理メモリにマップします。その後、プリフェッチアボート例外を発生させた命令の再試行に戻る必要があります。これでその命令がロードされ、実行されます。

プリフェッチアボートの生成時にはプログラムカウンタが更新されないため、lr_ABT はこの例外を発生させた命令の次の命令を指します。このハンドラは以下を使用して lr_ABTñ4 に復帰する必要があります。

    SUBS        pc,lr, #4

以下は、復帰アドレスをスタックにプッシュし、復帰時にそれをポップするハンドラのエントリ/終了コードを示しています。

    SUB        lr,lr,#4
    STMFD      sp!,{reglist,lr}
    ;...
    LDMFD      sp!,{reglist,pc}^

Thumb 状態で例外が発生する場合を除き、このハンドラの復帰命令(SUBS pc,lr,#4)によって、プログラムカウンタはアボートされた命令のアドレスに変更されます。プログラムカウンタは例外発生前に更新されないため、アボートされた命令の位置は(pc - 4)となります。したがって、プロセッサが lr_mode に格納する値は pc となります。

データアボートハンドラからの復帰

ロード命令またはストア命令によってメモリへのアクセスが試行されるとき、プログラムカウンタは更新されています。lr_ABT に格納される(pc - 4)の値は、例外が発生したアドレスから 2 つ先の命令を指します。MMU が存在し、MMU によって適切なアドレスが物理メモリにマップされた場合には、アボートされた命令の実行を再試行できるように、データアボートハンドラはこのアボートされた元の命令に戻る必要があります。したがって復帰アドレスは lr_ABT の値よりも 2 ワード(8 バイト)少ない値となり、復帰命令は以下のようになります。

    SUBS       pc, lr, #8

以下は、復帰アドレスをスタックにプッシュし、復帰時にそれをポップするハンドラのエントリ/終了コードを示しています。

    SUB        lr,lr,#8
    STMFD      sp!,{reglist,lr}
    ;...
    LDMFD        sp!,{reglist,pc}^

Thumb 状態で例外が発生する場合を除き、このハンドラの復帰命令(SUBS pc,lr,#8)によって、プログラムカウンタはアボートされた命令のアドレスに変更されます。プログラムカウンタは例外発生前に更新されるため、アボートされた命令の位置は(pc - 6)となります。したがって、プロセッサが lr_mode に格納する値は(pc + 2)となります。

Copyright © 2002-2006 ARM Limited. All rights reserved.ARM DUI 0203GJ
Non-Confidential