Zig版ASP3カーネルのスタートアップ
こんにちは、めのんです!
今朝に続いてZig版TOPPERS/ASP3カーネルの話題です。
前回は大まかなディレクトリ構成を見ただけでしたので、今回から本格的にコードを見ていきたいと思います。 何でもそうですが、プログラムのソースコードを読むのは起動直後の処理から手を付けるのがいいですよね。 というわけで、今回も起動直後の処理から見ていきます。
スタートアップルーチンというのはCPUにリセット信号が入った直後に呼び出される処理です。 普通、その中では割り込みの制御やスタックポインタの設定から始まって、.bssセクションのゼロクリアや.dataセクションのROMからRAMへの転送などが行われます。
C版のASP3カーネルでは、ARMの場合arch/arm_gcc/common/start.Sにスタートアップルーチンが定義されていました。 ところが、Zig版にはstart.Sもstart.zigも見当たりません。
start.Sで定義されていたスタートアップルーチンの先頭アドレスに付けられたラベルが「start」でしたので、この名前で検索してみました。 するとZig版ではどうやらcore_kernel_impl.zigにスタートアップルーチンが定義されているようです。
中身はほとんどインラインアセンブラで記述されているので、最初と最後の部分だけを引用したいと思います。
fn start() callconv(.Naked) noreturn { asm volatile( \\ .global start \\ start: (中略) [sta_ker] "s" (startup.sta_ker), ); unreachable; }
普通にZigの勉強をしていても、なかなか見ることができないキーワードが並んでいます。
callconvというのは文字通りコーリングコンベンションを変更するためのもので、.Nakedを指定していると関数のプロローグやエピローグが生成されないそうです。
普通は関数に入ると、いったんフレームポインタをスタックに待避してからその時点のスタックポインタをフレームポインタに格納します。 場合によっては汎用レジスタの待避をやっているかもしれません。 関数から抜ける際にはフレームポインタを元に戻して、スタックから取り出した呼び出し元アドレスに制御を移します。 そういうプロローグやエピローグを一切生成しないということだと理解しました。
noreturnは一種の型のようで、breakやcontinueなども含めて戻れない式?の評価結果の型のようです。 スタートアップルーチンはどこにも戻ることができませんので当然だと思います。
関数の最後に現れるunreachableは文字通り到達不可を明示的に宣言するためのものです。 何らかの間違いでここに到達してしまうとassertion failureになるようです。
関数の中のほとんどを占める部分はasm volatileで始まるインラインアセンブラです。 この内容については今回は触れません。 ただ、最後に登場するsta_kerだけは別です。
sta_kerはASP3カーネルをスタートさせるためのサービスコールです。 次回Zig版ASP3を扱う際には、sta_kerから見ていきたいと思います。
それでは!!