6.6.3. C 言語およびアセンブリ言語を使用した SVC ハンドラ

トップレベルのハンドラは常に ARM アセンブリ言語で記述する必要がありますが、各 SVC を処理するルーチンはアセンブリ言語でも C 言語でも記述できます。この点に関する制約条件については、スーパーバイザモードでの SVC の使用を参照して下さい。

トップレベルのハンドラでは BL(リンク付き分岐)命令を使用して適切な C 関数にジャンプします。SVC 番号はアセンブリルーチンによって r0 にロードされるため、この値は最初のパラメータとして C 関数に渡されます。C 関数はこの値を switch() ステートメントなどで使用できます。

Example 6.6SVC_Handler ルーチンには、以下の行を追加できます。

    BL    C_SVC_Handler     ; Call C routine to handle the SVC

Example 6.8 は、C 関数の実装方法を示しています。

Example 6.8. 

void C_SVC_handler (unsigned number)
{
    switch (number)
    {
        case 0 :/* SVC number 0 code */
            break;
        case 1 :/* SVC number 1 code */
            break;
        ...
        default :                /* Unknown SVC - report error */
    }
}

場合によってスーパーバイザスタック空間には制限があるため、大量のスタック空間を必要とする関数の使用は避けて下さい。

    MOV     r1, sp        ; Second parameter to C routine...
                          ; ...is pointer to register values.
    BL    C_SVC_Handler   ; Call C routine to handle the SVC

トップレベルのハンドラがスタックポインタの値を第 2 パラメータ(r1)として C 関数に渡すことで、C 言語で記述した SVC ハンドラとの間で値を受け渡すことができます。

また、この C 関数はレジスタの値にアクセスできるように以下のように変更します。

void C_SVC_handler(unsigned number, unsigned *reg)

これでこの C 関数は、メインアプリケーションコード内で SVC 命令が検出されたときにレジスタに保持されている値にアクセスできます(Figure 6.4 参照)。値はレジスタから以下のように読み出し、

    value_in_reg_0 = reg [0];
    value_in_reg_1 = reg [1];
    value_in_reg_2 = reg [2];
    value_in_reg_3 = reg [3];

以下のように書き戻します。

    reg [0] = updated_value_0;
    reg [1] = updated_value_1;
    reg [2] = updated_value_2;
    reg [3] = updated_value_3;

これにより、更新された値が適切なスタック位置に書き込まれ、トップレベルのハンドラによってレジスタに復元されます。

Figure 6.4. スーパーバイザスタックへのアクセス

スーパーバイザスタックへのアクセス
Copyright © 2002-2006 ARM Limited. All rights reserved.ARM DUI 0203GJ
Non-Confidential