ぐだぐだ低レベルプログラミング(90)ARM64(AArach64)、ロードストア命令その1

Joseph Halfmoon

今回からロードストア命令に入ります。気が重いです。Armは下手なCISC(多分x86のことだよ)よりもアドレシングモードが複雑怪奇。オペランドによっては特例的な規則もあります。64ビット化したおかげで、バイト、ハーフワード、ワードに加えてダブルワード(SIMD考えるともっと)あり、それに符合がからんで大変。

※「ぐだぐだ低レベルプログラミング」投稿順indexはこちら

最初にお断りしておきますが、対象にしている Arm Cortex-AクラスのCPUの場合、メモリとのロードストアを行う場合、命令の裏側では大物が暗躍しています。

    • 論理アドレスから物理アドレスへの変換(メモリマネジメント)
    • 階層的なメモリサブシステム(キャッシュ)

しかしそいつらに踏み込むと何をやっているのだかわからなくなってしまうので、今はロードストア「命令」に注力。上記のような者どもは「見て見ぬふり」をする所存です。

Arm v8の場合、

    • ロード命令はメモリからレジスタへのロード
    • ストア命令はレジスタからメモリへのストア

というところは、RISCの大原則にのっとってはいます。どこかのCISCのようにメモリからメモリへの転送命令のような「複雑」な命令はありません。しかし、私は言いたいです。

アドレシングモード、どこかのCISCより複雑だろ

と。

アドレシングモードを端的に言えば、メモリのアドレス(論理アドレス)を作るための仕組みです。単純な変数もありますが、配列あり、構造体あり、ポインタありです。強力なアドレシングモードはコンパイラを助ける?のかもしれません。でもRISC-V見たら単純なアドレシングモードで足りてるじゃん。

単独の汎用レジスタへのロード命令で使うアドレシング

まずは今回、実際に命令を動かしてみるのを1回お休みして、単独の汎用レジスタへのロード命令、ニーモニック的にはLDRとかLDURとか、で使われる基本のアドレシングモードを図にしておこうと思いました。整理しておかないと忘れてしまいそうなので。LDRとか書きましたが、オペランドのサイズによってLDRB(符合付バイト)とかLDRUB(符合無バイト)とかサイズと符合が追加され、一族のメンバは多数です。そしてオペランドのサイズはアドレス計算にも一部影響するのです。

なお、アドレス計算に使うオフセットにも符合付、符合無ありますが、オペランドの符合付、無とは無関係です。

ベースレジスタ+オフセット9ビット

9ビットのオフセット即値を符合拡張してベースレジスタに加えてアドレスを生成します。一番分かりやすいなあ。オフセットに何も書かねば0とみなされるので、ベースレジスタオンリもこのモードで表現できます。書式としては以下です。

    • [base, #imm9]
    • [base]

baseのところには、汎用レジスタx0-x30、およびSP(スタックポインタ)を当てはめることができます。ただしSPを使うときはSP独特のアライメント縛りのルールがあるので注意せんとなりません。

bimm9

ベースレジスタ+オフセット12ビット

12ビットのオフセット即値をゼロ拡張してベースレジスタに加えてアドレスを生成します。オプショナルですが、加えるオフセット即値に下駄(スケール)をはかせることができます。オペランドがワードなら00、ダブルワードなら000です。

    • [base, #imm12]

bimm12

ベースレジスタ+オフセットレジスタ32ビット

32ビットのWレジスタが保持するオフセット値を符合付あるいは符合無の拡張を施してベースレジスタに加えてアドレスを生成します。これまたオプショナルで加えるオフセット即値に下駄(スケール)をはかせることができます。

    • [base, Wm, (S|U)XTW #imm]

段々複雑になってきたなあ。

bregW

ベースレジスタ+オフセットレジスタ64ビット

64ビットのXレジスタが保持するオフセット値をベースレジスタに加えてアドレスを生成します。これまたオプショナルで加えるオフセット即値に下駄(スケール)をはかせることができます。

    • [base, Xm, LSL #imm]

bregX

PC相対

64ビットのプログラムカウンタ値に19ビットの即値を符合したものを加えてアドレスを生成します。19ビットの即値には漏れなく下位に00が付加されるので、±1Mバイトの範囲を指定することが可能です。アセンブラ記述上はラベルでメモリを指定します。

    • label

Literal

プリ・インデックスド

9ビットのオフセット即値を符合拡張してベースレジスタに加えてアドレスを生成するのは、最初にでてきたベース+オフセット9ビットと同じです。しかし、こいつがすごいのは、計算結果のアドレスをベースに「書き戻し」できることです。RISCのクセに副作用だぜ。まあ、RISCらしからぬARMの伝統か?表記的には以下のようです。後ろのビックリマーク(エクスクラメーションマーク)が書き戻しのおしるし。

    • [base, #imm9]!

Pre

ポスト・インデックスド

論理アドレスとして使うのは、Base Registerが保持するアドレスです。別途、9ビットのオフセット即値を符合拡張してベースレジスタに加えた値をベースに「書き戻し」します。後から(ポスト)加えるので表記的には以下のようです。

    • [base], #imm9

こちらにはビックリマークが無いので、つい見過ごしてしまいそうな表記法です(個人の感想です。)Post

 

どうこういって、プリもポストも便利だから使ってしまいそうだけれども、それでもRISCか?と問いたいデス。

ぐだぐた低レベルプログラミング(89)ARM64(AArach64)、除算命令 へ戻る

ぐだぐだ低レベルプログラミング(91)ARM64(AArach64)、ロードストア命令その2 へ進む