5.21 スーパーバイザモードでの SVC の使用

スーパーバイザモードで SVC を呼び出す場合は、LR と SPSR の元の値が失われないように SVC LR および SPSR を保存しておく必要があります。

SVC 命令が実行される場合、以下のようになります。

  1. プロセッサがスーパーバイザモードに入ります。

  2. CPSR が SVC SPSR に格納されます。

  3. リターンアドレスが SVC LR に格納されます。

プロセッサが既にスーパーバイザモードにある場合、SVC LR と SPSR を格納していなければ破壊されます。

例えば、特定の SVC 番号のハンドラルーチンが別の SVC を呼び出す場合は、そのハンドラルーチンで SVC LR と SPSR の両方をスタックに格納する必要があります。この動作の結果、ハンドラが呼び出されるごとに、ハンドラを呼び出した SVC に続く命令に復帰するために必要な情報が保存されることが保証されます。以下の例は、この方法を示しています。

SVC ハンドラ

    AREA SVC_Area, CODE, READONLY     PRESERVE8     EXPORT SVC_Handler     IMPORT C_SVC_Handler T_bit EQU 0x20 SVC_Handler     PUSH     {R0-R3,R12,lr}       ; レジスタを保存する。MOV      R1, sp               ; ポインタをパラメータに設定する。MRS      R0, SPSR             ; SPSR を取得する。PUSH     {R0,R3}              ; SPSR をスタックおよび別の                                   ; レジスタを保存して、                                   ; 8 バイトで整列されたスタックを保持する。; 入れ子になった SVC でのみ必要。TST      R0,#0x20             ; Thumb ステートで発生したか?LDRHNE   R0,[lr,#-2]          ; はい:ハーフワードをロードし...BICNE    R0,R0,#0xFF00        ; ...コメントフィールドを抽出する。LDREQ    R0,[lr,#-4]          ; いいえ:ワードをロードし...BICEQ    R0,R0,#0xFF000000    ; ...コメントフィールドを抽出する。; R0 は SVC 番号を含む                                   ; R1 はスタックレジスタへのポインタを含む                                    ; BL       C_SVC_Handler        ; SVC を処理するための C ルーチンを呼び出す。POP      {R0,R3}              ; スタックから SPSR を取得する。MSR      SPSR_cf, R0          ; SPSR を復元する。LDM      sp!, {R0-R3,R12,pc}^ ; レジスタを復元し、復帰する。END

C/C++ で記述した入れ子構造の SVC

C または C++ で入れ子になった SVC を記述できます。コンパイラによって生成されるコードは、必要に応じて lr_SVC のストアと再ロードを実行します。

関連する概念
5.7 例外に対するプロセッサの応答
非機密扱いPDF file icon PDF 版ARM DUI0471JJ
Copyright © 2010-2013 ARM.All rights reserved.