ロード命令 (1) ()
これから ARM64 の個々の命令の解説を順次進めていきますが、 まず最初に命令の中で種類が最も多く、複雑なロード命令を 説明することにします。 このロード命令を攻略すると ARM64 の他の命令 (ストア命令も) の複雑さは大したことありません。
ロード命令(LDR)はメモリに格納されている値をレジスタに読み込み、 ストア命令はレジスタに入っている値をメモリに書き出す命令です。 コンピュータは、ほとんどすべての作業をメモリを介して行うので、 ロード/ストア命令はよく使われます。
レジスタ-メモリ転送 | 読み | 命令 |
---|---|---|
メモリからレジスタへコピー | ロード | LDR |
レジスタからメモリへコピー | ストア | STR |
レジスタからレジスタへコピー | ムーブ | MOV |
アドレッシング
プログラム自身もデータもファイルから読み出されて、メモリに格納されてから処理を行います。 したがって、メモリに対して読み書きするロード/ストア命令は大変重要です。 ロード/ストア命令では読み書きするメモリの位置(メモリアドレス)を 指定する必要がありますが、この位置の指定方法を「アドレッシング」 と呼びます。CPUの種類(x86, x64, ARM, Arm64、PowerPC など)によって、 「アドレッシング」の方法が異なるため、新しい CPU のアセンブリ言語を 習得しようとする場合、「アドレッシング」の方法を早く理解することがコツです。
ARM64のロード/ストア命令のアドレッシングには、大きく分けて イミディエートオフセット、レジスターオフセット、 リテラル(プログラムカウンタ相対オフセット) の3種類があります。 今回は使用頻度が高くて複雑なイミディエートオフセットと レジスターオフセット の2種類を紹介します。
上の図は、ARM64でメモリの位置を指定する方法を示しています。 ベースレジスタとして働く汎用レジスタまたはスタックポインタの示す メモリの番地を基本として、オフセットと呼ばれる数値を加減算した アドレスのデータを読み書きします。 図の中の「オフセット」が 定数のものがイミディエートオフセット、このオフセットもレジスタに 格納された値を使うものがレジスターオフセットです。
イミディエートオフセット
レジスタ (Xn または SP) が格納している値をメモリアドレスとして、 その値に定数を加えてメモリアドレスとするアドレッシングを イミディエートオフセット (immediate offset) といいます。 ARM64では、64ビットレジスタにメモリ中のアドレスを格納して、 そのメモリアドレスに対してデータを読み書きします。 レジスタが格納しているメモリアドレスに対して、比較的小さい 整数値、例えば +16 とか -200 といった定数値を加えたアドレスに アクセスしたい場合があります。 そのような場合のために命令自体に比較的小さい整数値を 埋め込むことができます。 この値をイミディエートと呼び、日本語では即値と訳されます。
符号付き 9 ビットオフセット
ロード命令では、 9ビットの符号付き定数(+255..-256)を使う アドレッシングとして、プレインデックスとポストインデックス があります。これらの 2 種類はベースレジスタにオフセットを 加えてベースレジスタを更新します。 また、LDUR 系の命令として ベースレジスタへの変更を行わない符号付き 9 ビットオフセット のアドレッシングがあります。
プレインデックス
プレインデックスは、ベースレジスタと呼ぶスタックポインタ (SP) または 64 ビット汎用レジスタ (Xn) が格納している アドレスに定数を加えたメモリアドレスから読み出し、 そのアドレスをベースレジスタに書き戻します。 結果として、ベースレジスタの値に定数を加えたメモリアドレス を使ってベースレジスタを「事前に」更新し、そこにアクセス していることになります。ベースレジスタを「事前に」更新する ことから「プレインデックス」と呼んでいます。 次の擬似コードでは、memory[ adr ] でメモリアドレス adr に 格納されている内容を示します。 base はベースレジスタ(Xn または SP)、Xt は転送先のレジスタを 示します。 プレインデックスはオペランドの最後に「!」を付けて表します。
LDR Xt, [base, #simm9]! // プレインデックス // プレインデックス base = base + simm9; Xt = memory[base];
ポストインデックス
ポストインデックスはベースレジスタの示すメモリアドレスから 読みだした後、オフセットに指定した定数をベースレジスタに加算します。 つまり、ベースレジスタのメモリアドレスにアクセスした「後に」 ベースレジスタを別のメモリアドレスに更新することから 「ポストインデックス」と呼んでいます。
LDR Xt, [base], #simm9 // ポストインデックス
// ポストインデックス
Xt = memory[base];
base = base + simm9;
Unscaled
9ビットの符号付き定数を使うアドレッシングモードにはもう一つあって、 LDUR 命令は、ポストインデックスでもプレインデックスでもない 動作をします。ベースレジスタにオフセットを加えたメモリから ロードするのは同じですが、ベースレジスタ base の値を更新しません。
LDUR Xt, [base, #simm9] // base への書き戻しなし Xt = memory[base + simm9];
この LDUR 命令も「LDR」というニーモニック(命令の名前)のほうが 適していると思いますが、ARM (会社の方) は次に説明する符号無し 12 ビットオフセットアドレッシングの方に「LDR」というニーモニックを 割り当てることにしたようです。「U」は Unscaled の略で、 次の符号無し12ビットオフセットと異なって、 オフセットに対して転送するバイト数を乗算するスケーリングを 行わないことを意味しています。 いつも LDR というニーモニックを 使っていれば、必要な場合に LDUR 命令と LDR 命令の符号無し 12 ビット オフセットをアセンブラが自動的に選択して使ってくれるので、 通常はこのアドレッシングモードを意識する必要はありません。 転送バイト数の倍数になっていないオフセット値で、かつオフセットが +255 .. -256 を超える場合に、アセンブラはエラーを出力します。
符号無し12ビットオフセット
ベースレジスタに格納されている値に符号無し 12 ビットの即値 (0 .. 4095) を加えた値のメモリアドレスに格納されているメモリの内容を レジスタにコピーします。
LDR Xt, [base, #uimm12] // base に書き戻さない Xt = [base + uimm12 * scale]; // scale = 1,2,4,8
12ビットの定数は転送するバイト数にしたがって 1、2、4、8 倍に スケーリングされます。したがって実際のオフセットは 1 バイトの ロードでは (0 .. 4095)、ハーフワードでは (0 .. 8190)、ワード (32ビット) では (0 .. 16380)、ダブルワード (64ビット) では (0 .. 32760) の範囲のオフセットを使用することができます。 C 言語の配列で考えると 4096 個の要素に定数インデックスで アクセスできることになります。 符号付き 9 ビットオフセットと異なって負のオフセットは使えず、 転送するバイト数を倍数とするオフセット値に限定されます。
レジスタオフセット
ベースレジスタ (Xn または SP) が保持しているメモリアドレスに、 インデックス用のレジスタが格納しているオフセット値を加えた メモリアドレスの内容を転送先レジスタ(Xt)にコピーします。 インデックス用レジスタ (Rm) には 32ビットレジスタ (Wm) または 64ビットレジスタを指定できます。 オフセット値は 32ビットレジスタならば4倍、 64ビットレジスタの場合は8倍するように指定することもできます。 32ビットレジスタの場合でも符号拡張を指定することが可能なため、 負のオフセット値を使うことができます。
64ビットのロードを例にすると、次のような命令の形式となります。
LDR Xt, [base, Wm {, SXTW|UXTW {#0|#3}} ] LDR Xt, [base, Xm {, LSL|SXTX {#0|#3}} ] Xt = memory[base + Rm {* 8} ]
32ビットのロードの場合は、次のようにシフト量が #2 (4倍) を指定できます。
LDR Wt, [base, Wm {, SXTW|UXTW {#0|#2}} ] LDR Wt, [base, Xm {, LSL|SXTX {#0|#2}} ] Wt = memory[base + Rm {* 4} ]
命令中の SXTW | UXTW または LSL | SXTX は拡張(extend)指定子で、 インデックス用レジスタの値を 32ビットから 64ビットに拡張する 場合に符号拡張を行う(SXTW)かどうかを指定します。 64ビットの場合に LSL を指定すると転送バイト数倍のシフトを指定できます。 シフト量は省略可能で LSL でない場合は #0 になります。 シフト量は任意のビット数が指定できるわけでは無く、 「シフトするか/しないか」の2択です。アセンブラのオペランドの記述には 転送バイト数に応じたシフトするビット数を指定する必要があります。
ロード命令の概要
ロード命令には、データのメモリー中でのサイズと転送先のレジスタの サイズが異なる命令が次のように 9種類あります。読み込むデータが 1 バイト (8ビット)から 8 バイト (64ビット)にもかかわらず、転送先のレジスタが 32ビットと64ビットの2種類の指定しかできないために命令が多くなっています。
メモリのデータサイズとレジスタのサイズの組み合わせによっては 命令が存在しない組み合わせがあります。ここでは区別しやすいように、 存在する 9 種類をデータサイズの大きいものから順に番号を付けています。
メモリ | 符号 | 転送先(32) | 転送先(64) |
---|---|---|---|
ビット数 | Wt | Xt | |
64ビット | 無符号 | - | LDR [1] |
符号付 | |||
32ビット | 無符号 | LDR [2] | |
符号付 | LDRSW [3] | ||
16ビット | 無符号 | LDRH [4] | - |
符号付 | LDRSH [5] | LDRSH [6] | |
8ビット | 無符号 | LDRB [7] | - |
符号付 | LDRSB [8] | LDRSB [9] |
小さいビット幅のデータをビット幅が大きいレジスタに転送する場合には、 データのビット幅を広げる必要があります。この時にレジスタの上位ビットに 0 を設定(ゼロ拡張)するか、データを符号付きの整数と考えてデータの最上位ビットを レジスタの上位ビットにコピー(符号拡張)するかで2種類の拡張方法があります。 上の表で符号無しの場合はゼロ拡張、符号付きの場合は符号拡張になります。
ロード命令の詳細
メモリのデータサイズとレジスタのサイズの組み合わせ毎にデータサイズの 大きいものから順に紹介します。 9 種類の命令はそれぞれ6種類の同じ アドレッシングを使うことができます。
6種類のアドレッシングは、次のものです。
- 9ビット符号付即値+ポストインデックス
- 9ビット符号付即値+プレインデックス
- 9ビット符号付即値
- 12ビット符号なし即値
- 32ビットレジスタオフセット
- 64ビットレジスタオフセット
[1] LDR ダブルワード(64ビット) → 64ビット
ARM64 にとって、一番自然なサイズである64ビットのデータをメモリから 読み取って、64 ビットレジスタに格納する命令です。 データとレジスタのビット幅が等しいため、符号の有無で命令のバリエーション はありません。
LDR Xt, [base], #simm9 // ポストインデックス LDR Xt, [base, #simm9]! // プレインデックス LDUR Xt, [base, #simm9] LDR Xt, [base {,#uimm12} ] // 符号なしオフセット(8の倍数) [0 - 32760] LDR Xt, [base, Wm {,SXTW|UXTW {#0 | #3}} ] // レジスタオフセット LDR Xt, [base, Xm {,LSL|SXTX {#0 | #3}} ] // レジスタオフセット
オフセットの値によって、9ビットの符号付オフセットのLDUR命令と、 12ビットの符号なしオフセットのLDR命令のどちらを使うかはアセンブラが 自動的に決めてくれます。LDUR命令を使う必要はなく、常にLDR命令を 使えば大丈夫です。 下のリストは即値オフセットのロード命令と GNU as の翻訳結果のビットパターンです。 必要な場合は LDR 命令が LDUR 命令に変換されているのが分かります。
// 正整数で8の倍数 ldr x0, [x9, #8] |---+---|---+---|---+---|---+--0 11111001010000000000010100100000 --> LDR // LDURを指定 ldur x0, [x9, #8] |---+---|---+---|---+---|---+--0 11111000010000001000000100100000 --> LDUR // 8の倍数でない ldr x0, [x9, #9] |---+---|---+---|---+---|---+--0 11111000010000001001000100100000 --> LDUR // 正の整数でない ldr x0, [x9, #-8] |---+---|---+---|---+---|---+--0 11111000010111111000000100100000 --> LDUR // オフセットの範囲が9ビットを超える ldr x0, [x9, #512] |---+---|---+---|---+---|---+--0 11111001010000000000010100100000 --> LDR // LDUR のオフセットの範囲を超える ldur x0, [x9, #512] --> エラー
他のLDUR系の命令(LDURSW、LDURH、LDURSH、LDURB、LDURSB)も 同じように、必要な場合はアセンブラにより LDUR 命令に変換されます。
命令のエンコード
表中で simm9 は9ビットの符号付イミディエート値(-256 .. +255)、 uimm12 は符号なし12ビットイミディエート値(0 .. 4095) を示します。 Rn はベースアドレスを格納する汎用レジスタ(X0..X31)または スタックポインタ(SP)、Rt はデータの転送先となるレジスタです。
アクセスするメモリのデータサイズは命令先頭の 2bit が表しています。
LDR | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 1 1 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 1 1 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDUR | 1 1 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 1 1 | 1 1 1 | 0 | 0 1 | 0 1 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 1 1 | 1 1 1 | 0 | 0 0 | 0 1 | 1 | Rm | option | S | 1 0 | Rn | Rt |
[2] LDR ワード(32ビット) → 32ビット
メモリから 32 ビットのデータを読み取って、32 ビットレジスタに 格納する命令です。32ビットレジスタは W0 から W30 までありますが、 64ビットレジスタの下位 32 ビットに格納されます。上位32ビットは 0 に 設定されます。 データと転送先レジスタのビット幅が等しいため、 符号の有無で命令のバリエーションはありません。
LDR Wt, [base], #simm9 // ポストインデックス LDR Wt, [base, #simm9]! // プレインデックス LDUR Wt, [base, #simm9] LDR Wt, [base {,#uimm12} ] // 符号なしオフセット(4の倍数) [0 - 16380] LDR Wt, [base, Wm {,SXTW|UXTW {#0 | #2}} ] LDR Wt, [base, Xm {,LSL|SXTX {#0 | #2}} ]
命令のエンコード
LDR | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 1 0 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 1 0 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDUR | 1 0 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 1 0 | 1 1 1 | 0 | 0 1 | 0 1 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 1 0 | 1 1 1 | 0 | 0 0 | 0 1 | 1 | Rm | option | S | 1 0 | Rn | Rt |
[3] LDRSW 符号付きワード(32ビット) → 64ビット
メモリから 32 ビットのデータを読み取って、64 ビットレジスタに 符号拡張して格納する命令です。 32ビットのデータが 負(最上位ビットが「1」)の場合には、64ビットレジスタの 上位32ビットをすべて「1」とします。32ビットで負の値は 64ビットでも同じ負の値となります。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDR、LDRSW)があります。
LDRSW Xt, [base], #simm9 // ポストインデックス LDRSW Xt, [base, #simm9]! // プレインデックス LDURSW Xt, [base, #simm9] LDRSW Xt, [base {,#uimm12} ] // 符号なしオフセット(4の倍数) [0 - 16380] LDRSW Xt, [base, Wm {,SXTW|UXTW {#0 | #2}} ] LDRSW Xt, [base, Xm {,LSL|SXTX {#0 | #2}} ]
命令のエンコード
LDRSW | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 1 0 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 1 0 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDURSW | 1 0 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 1 0 | 1 1 1 | 0 | 0 1 | 1 0 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 1 0 | 1 1 1 | 0 | 0 0 | 1 0 | 1 | Rm | option | S | 1 0 | Rn | Rt |
[4] LDRH ハーフワード(16ビット) → 32ビット
メモリから 16 ビットのデータを読み取って、32 ビットレジスタに ゼロ拡張して格納する命令です。 32ビットレジスタの 上位16ビットをすべて「0」とします。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDRH、LDRSH)があります。
LDRH Wt, [base], #simm9 // ポストインデックス LDRH Wt, [base, #simm9]! // プレインデックス LDURH Wt, [base, #simm9] LDRH Wt, [base {,#uimm12} ] // 符号なしオフセット(2の倍数) [0 - 8190] LDRH Wt, [base, Wm {,SXTW|UXTW {#0 | #1}} ] LDRH Wt, [base, Xm {,LSL|SXTX {#0 | #1}} ]
命令のエンコード
LDRH | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 0 1 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 0 1 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDURH | 0 1 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 0 1 | 1 1 1 | 0 | 0 1 | 0 1 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 0 1 | 1 1 1 | 0 | 0 0 | 0 1 | 1 | Rm | option | S | 1 0 | Rn | Rt |
[5] LDRSH 符号付きハーフワード(16ビット) → 32ビット
メモリから 16 ビットのデータを読み取って、32 ビットレジスタに 符号拡張して格納する命令です。 16ビットのデータが 負(最上位ビットが「1」)の場合には、32ビットレジスタの 上位16ビットをすべて「1」とします。16ビットで負の値は 32ビットでも同じ負の値となります。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDRH、LDRSH)があります。
LDRSH Wt, [base], #simm9 // ポストインデックス LDRSH Wt, [base, #simm9]! // プレインデックス LDURSH Wt, [base, #simm9] LDRSH Wt, [base {,#uimm12} ] // 符号なしオフセット(2の倍数) [0 - 8190] LDRSH Wt, [base, Wm {,SXTW|UXTW {#0 | #1}} ] LDRSH Wt, [base, Xm {,LSL|SXTX {#0 | #1}} ]
命令のエンコード
LDRSH | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 0 1 | 1 1 1 | 0 | 0 0 | 1 1 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 0 1 | 1 1 1 | 0 | 0 0 | 1 1 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDURSH | 0 1 | 1 1 1 | 0 | 0 0 | 1 1 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 0 1 | 1 1 1 | 0 | 0 1 | 1 1 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 0 1 | 1 1 1 | 0 | 0 0 | 1 1 | 1 | Rm | option | S | 1 0 | Rn | Rt |
[6] LDRSH 符号付きハーフワード(16ビット) → 64ビット
メモリから 16 ビットのデータを読み取って、64 ビットレジスタに 符号拡張して格納する命令です。 16ビットのデータが 負(最上位ビットが「1」)の場合には、64ビットレジスタの 上位48ビットをすべて「1」とします。16ビットで負の値は 64ビットでも同じ負の値となります。 データより転送先レジスタが大きいため、符号の有無で2つの命令が 必要となりますが、16ビットから64ビットへの符号なし拡張(ゼロ拡張)はLDRH [4]と 同じ動作になるため、専用の命令はありません。
LDRSH Xt, [base], #simm9 // ポストインデックス LDRSH Xt, [base, #simm9]! // プレインデックス LDURSH Xt, [base, #simm9] LDRSH Xt, [base {,#uimm12} ] // 符号なしオフセット(2の倍数) [0 - 8190] LDRSH Xt, [base, Wm {,SXTW|UXTW {#0 | #1}} ] LDRSH Xt, [base, Xm {,LSL|SXTX {#0 | #1}} ]
命令のエンコード
LDRSH | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 0 1 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 0 1 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDURSH | 0 1 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 0 1 | 1 1 1 | 0 | 0 1 | 1 0 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 0 1 | 1 1 1 | 0 | 0 0 | 1 0 | 1 | Rm | option | S | 1 0 | Rn | Rt |
[7] LDRB バイト(8ビット) → 32ビット
メモリから 8 ビットのデータを読み取って、32 ビットレジスタに ゼロ拡張して格納する命令です。 32ビットレジスタの 上位24ビットをすべて「0」とします。 メモリ上のデータを1バイトずつ読み取るので、比較的使う機会が多い命令です。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDRB、LDRSB)があります。
LDRB Wt, [base], #simm9 // ポストインデックス LDRB Wt, [base, #simm9]! // プレインデックス LDURB Wt, [base, #simm9] LDRB Wt, [base {,#uimm12} ] // 符号なしオフセット [0 - 4095] LDRB Wt, [base, Wm {,SXTW|UXTW {#0}} ] LDRB Wt, [base, Xm {,LSL|SXTX {#0}} ]
命令のエンコード
LDRB | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 0 0 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 0 0 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDURB | 0 0 | 1 1 1 | 0 | 0 0 | 0 1 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 0 0 | 1 1 1 | 0 | 0 1 | 0 1 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 0 0 | 1 1 1 | 0 | 0 0 | 0 1 | 1 | Rm | option | S | 1 0 | Rn | Rt |
[8] LDRSB 符号付きバイト(8ビット) → 32ビット
メモリから 8 ビットのデータを読み取って、32 ビットレジスタに 符号拡張して格納する命令です。 8ビットのデータが 負(最上位ビットが「1」)の場合には、32ビットレジスタの 上位24ビットをすべて「1」とします。8ビットで負の値は 32ビットでも同じ負の値となります。 データより転送先レジスタが大きいため、符号の有無で2つの命令(LDRB、LDRSB)があります。 使う機会はあまりないと思います。
LDRSB Wt, [base], #simm9 // ポストインデックス LDRSB Wt, [base, #simm9]! // プレインデックス LDURSB Wt, [base, #simm9] LDRSB Wt, [base {,#uimm12} ] // 符号なしオフセット [0 - 4095] LDRSB Wt, [base, Wm {,SXTW|UXTW {#0}} ] LDRSB Wt, [base, Xm {,LSL|SXTX {#0}} ]
命令のエンコード
LDRSB | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 0 0 | 1 1 1 | 0 | 0 0 | 1 1 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 0 0 | 1 1 1 | 0 | 0 0 | 1 1 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDURSB | 0 0 | 1 1 1 | 0 | 0 0 | 1 1 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 0 0 | 1 1 1 | 0 | 0 1 | 1 1 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 0 0 | 1 1 1 | 0 | 0 0 | 1 1 | 1 | Rm | option | S | 1 0 | Rn | Rt |
[9] LDRSB 符号付きバイト(8ビット) → 64ビット
メモリから 8 ビットのデータを読み取って、64 ビットレジスタに 符号拡張して格納する命令です。 8ビットのデータが 負(最上位ビットが「1」)の場合には、64ビットレジスタの 上位56ビットをすべて「1」とします。8ビットで負の値は 64ビットでも同じ負の値となります。 使う機会はあまりないと思います。 データより転送先レジスタが大きいため、符号の有無で2つの命令が 必要となりますが、8ビットから64ビットへの符号なし拡張(ゼロ拡張)はLDRB [7]と 同じ動作になるため、専用の命令はありません。
LDRSB Xt, [base], #simm9 // ポストインデックス LDRSB Xt, [base, #simm9]! // プレインデックス LDURSB Xt, [base,#simm9] LDRSB Xt, [base {,#uimm12} ] // 符号なしオフセット [0 - 4095] LDRSB Xt, [base, Wm {,SXTW|UXTW {#0}} ] LDRSB Xt, [base, Xm {,LSL|SXTX {#0}} ]
命令のエンコード
LDRSB | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
post index | 0 0 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 0 | 1 | Rn | Rt | |||||||||||||||||||||
pre index | 0 0 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 1 | 1 | Rn | Rt | |||||||||||||||||||||
LDURSB | 0 0 | 1 1 1 | 0 | 0 0 | 1 0 | 0 | simm9 | 0 | 0 | Rn | Rt | |||||||||||||||||||||
unsigned 12 | 0 0 | 1 1 1 | 0 | 0 1 | 1 0 | uimm12 | Rn | Rt | ||||||||||||||||||||||||
register | 0 0 | 1 1 1 | 0 | 0 0 | 1 0 | 1 | Rm | option | S | 1 0 | Rn | Rt |