演算命令 ()
演算命令とは四則演算、論理演算、比較などを行う命令群です。 ARM64 では演算命令に3つのレジスタを指定することができます。 3番目の位置には、レジスタ以外に定数やレジスタの内容をシフトした値を指定することもできます。
add x1, x2, x3 // x1 = x2 + x3
上の例では、x1 はデスティネーションレジスタ (Rd) で演算結果が最終的に代入されます。 x2 は第1ソースオペランドレジスタ (Rn) 、x3 の部分は第2オペランドと呼んで、 レジスタ、メモリアドレス、定数値を指定できます。
// すべてを同じレジスタにすることも可能
add x1, x1, x1 // x1 = x1 + x1 = x1 * 2
演算命令の場合、第2オペランドは「そのオペランドレジスタの内容をシフトしたもの」 という指定が可能で、次のように1命令でシフト演算まで実行することができます。
add x1, x2, x3 LSL #20 // x1 = x2 + (x3 << 20)
シフト演算 には LSL、LSR 、ASR を指定することができます。
アドレッシングモード
以下の加減算の命令のアドレッシングモードには、単純なレジスタ指定、シフトレジスタ、イミディエート(定数指定)、 拡張レジスタの4種類がありますが、命令によって使えるアドレッシングモードが 異なっているため、注意が必要です。
ニーモニックの末尾が S の命令は、演算結果にしたがって条件フラグが更新されます。
アドレッシング | ||||
---|---|---|---|---|
演算 | レジスタ | シフトレジスタ | イミディエート | 拡張レジスタ |
加算 | ADD | ADD | ADD | |
加算 | ADDS / CMN | ADDS / CMN | ADDS / CMN | |
減算 | SUB / NEG | SUB / NEGS | SUB | |
減算 | SUBS / CMP | SUBS / CMP | SUBS / CMP | |
論理積 | AND | AND | ||
論理積 | ANDS / TST | ANDS / TST | ||
ビットクリア | BIC | |||
ビットクリア | BICS | |||
否定論理和 | ORN | |||
論理和 | ORR | ORR | ||
否定排他的論理和 | EON | |||
排他的論理和 | EOR | EOR | ||
キャリー込み加算 | ADC | |||
キャリー込み加算 | SBC |
イミディエート(定数指定)
加減算命令の定数指定は以下の形式です。論理演算のイミディエートアドレッシングは後述します。
ADD Xd, Xn, #uimm12 {, LSL #12} ADD Wd, Wn, #uimm12 {, LSL #12}
この命令はレジスタ(Rn)が格納している値に定数を加算または減算して、指定したレジスタ (Rd) に書き込みます。 定数は12ビットの左シフト(4096倍)を指定することもできます。定数値は 0 から 4095 の範囲です。定数のシフトを指定する場合は LSL #12 を加えます。
シフトレジスタ(シフト済みレジスタ指定)
ADD Xd, Xn, Xm {, shift #amount} ADD Wd, Wn, Wm {, shift #amount}
Rn と Rm を加えて、Rd に設定します。 Rm の内容は演算前にシフト演算(LSL、LSR 、ASR)を指定することができます。シフト量は64bitレジスタでは 0 - 63、32bitレジスタでは 0 - 31 の範囲となります。
拡張レジスタ
レジスタのデータを 8 ビットから 64 ビットへ符号付拡張する等が可能なアドレッシングモードです。
ADD Xd, Xn, Wm {,extend {#amount}} ADD Xd, Xn, Xm {,extend {#amount}}
この命令はレジスタ(Rn)が格納している値に符号拡張またはゼロ拡張したレジスタ(Rm)の値を加算または減算して、指定したレジスタ (Rd) に書き込みます。データ拡張後に左シフトする量を 0 から 4 の範囲で指定できます。 拡張するデータは byte、halfword、word、doubleword が可能です。
option | extend | 意味 | |
---|---|---|---|
32 bit | 64 bit | ||
000 | UXTB | UXTB | 8bitから無符号拡張 |
001 | UXTH | UXTH | 16bitから無符号拡張 |
010 | LSL/UXTW | UXTW | 32bitから無符号拡張 |
011 | UXTX | LSL/UXTX | 64bitから無符号拡張 |
100 | SXTB | SXTB | 8bitから符号付拡張 |
101 | SXTH | SXTH | 16bitから符号付拡張 |
110 | SXTW | SXTW | 32bitから符号付拡張 |
111 | SXTX | SXTX | 64bitから符号付拡張 |
拡張後に適用する左シフト量を 0 - 4 の範囲で指定できます。LSLの場合は必須です。
加減算
単純な加減算はアドレッシングとしてシフトレジスタ、イミディエート、拡張レジスタの3種類を使うことができます。
ADD
レジスタとレジスタ、またはレジスタと定数の加算を行います。演算結果で条件フラグ (NZCV レジスタ) は変化しません。
ADD Xd, Xn, Xm {,shift #amount} ADD Wd, Wn, Wm {,shift #amount} ADD Xd|SP, Xn|SP, #uimm12 {, LSL #12} ADD Wd|WSP, Wn|WSP, #uimm12 {, LSL #12} ADD Xd|SP, Xn|SP, Rm {,extend {#amount}} ADD Wd|WSP, Wn|WSP, Rm {,extend {#amount}}
ADDS
レジスタとレジスタ、またはレジスタと定数の加算を行います。演算結果に応じて条件フラグ (NZCV レジスタ) のビットを更新します。
ADDS Xd, Xn, Xm {,shift #amount} ADDS Wd, Wn, Wm {,shift #amount} ADDS Xd|SP, Xn|SP, #uimm12 {,LSL #12} ADDS Wd|WSP, Wn|WSP, #uimm12 {,LSL #12} ADDS Xd|SP, Xn|SP, Rm {,extend {#amount}} ADDS Wd|WSP, Wn|WSP, Rm {,extend {#amount}}
SUB
レジスタからレジスタ、またはレジスタから定数を減算します (Rd = Rn - Rm|imm)。 演算結果で条件フラグ (NZCV レジスタ) は変化しません。
SUB Xd, Xn, Xm {,shift #amount} SUB Wd, Wn, Wm {,shift #amount} SUB Xd|SP, Xn|SP, #uimm12 {,LSL #12} SUB Wd|WSP, Wn|WSP, #uimm12 {,LSL #12} SUB Xd|SP, Xn|SP, Rm {,extend {#amount}} SUB Wd|WSP, Wn|WSP, Rm {,extend {#amount}}
NEG
レジスタの値を正負反転します(Rd = - Rm)。演算結果で条件フラグ (NZCV レジスタ) は変化しません。 この命令はアセンブラで SUB に翻訳されます。
NEG Xd, Xm {,shift #amount} // SUB Xd, XZR, Xm {,shift #amount} と同じ NEG Wd, Wm {,shift #amount} // SUB Xd, WZR, Xm {,shift #amount} と同じ
SUBS
レジスタからレジスタ、またはレジスタから定数を減算します(Rd = Rn - Rm|imm)。演算結果に応じて条件フラグ (NZCV レジスタ) のビットを更新します。キャリーフラグはボローが発生しない (Rn ≧ Rm) 場合に 1、ボローが発生する (Rn < Rm) 場合は 0 となります。
内部的には、減数の1の補数を求め、キャリーフラグを 1 にした後、キャリー込み加算(ADCS) を行っているようです。 減数の 1 の補数にキャリーフラグの 1 を加えると 2 の補数(減数 * -1)を求めたことになり、被減数と加算することで結果的に「被減数 - 減数」という減算となります。「被減数 ≧ 減数」のとき、「被減数 + (減数 * -1)」の符号付き加算ではキャリーセットされ、「被減数 < 減数」のとき、「被減数 + (減数 * -1)」の符号付き加算ではキャリークリアされます。 分かり難いですが、以上がボローが発生するとキャリーフラグが 0 になる理由です。
SUBS Xd, Xn, Xm {,shift #amount} SUBS Wd, Wn, Wm {,shift #amount} SUBS Xd|SP, Xn|SP, #uimm12 {, LSL #12} SUBS Wd|WSP, Wn|WSP, #uimm12 {, LSL #12} SUBS Xd|SP, Xn|SP, Rm {,extend {#amount}} SUBS Wd|WSP, Wn|WSP, Rm {,extend {#amount}}
NEGS
レジスタの値を正負反転します(Rd = - Rm)。演算結果に応じて条件フラグ(NZCV レジスタ) のビットを更新します。 この命令はアセンブラで SUBS に翻訳されます。
NEGS Xd, Xm {,shift #amount} // SUBS Xd, XZR, Xm {,shift #amount} と同じ NEGS Wd, Wm {,shift #amount} // SUBS Wd, WZR, Wm {,shift #amount} と同じ
CMP
レジスタからレジスタ、またはレジスタから定数の減算を行って、演算結果に対応した条件フラグを設定します。 減算算結果自身は使用しません。 この命令はアセンブラで SUBS に翻訳されます。
CMP Wn|WSP, #imm {,shift} // SUBS WZR, Wn|WSP, #imm {,shift} と同じ CMP Xn|SP, #imm {,shift} // SUBS XZR, Xn|SP, #imm {,shift} と同じ CMP Wn|WSP, Wm {,extend {#amount}} // SUBS WZR, Wn|WSP, Wm {,extend {#amount}} と同じ CMP Xn|SP, R m {,extend {#amount}} // SUBS XZR, Xn|SP, R m {,extend {#amount}} と同じ CMP Wn, Wm {,shift #amount} // SUBS WZR, Wn, Wm {,shift #amount} と同じ CMP Xn, Xm {,shift #amount} // SUBS XZR, Xn, Xm {,shift #amount} と同じ
CMN
レジスタ Rm または定数に -1 を乗じたものとレジスタ Rn またはスタックポインタ(SP)を比較します。 この命令はアセンブラで ADDS に翻訳されます。
CMN Wn|WSP, #imm {,shift} // ADDS WZR, Wn|WSP, #imm {,shift}と同じ CMN Xn|SP, #imm {,shift} // ADDS XZR, Xn|SP, #imm {,shift}と同じ CMN Wn|WSP, Wm {,extend {#amount}} // ADDS WZR, Wn|WSP, Wm {,extend {#amount}}と同じ CMN Xn|SP, Rm {,extend {#amount}} // ADDS XZR, Xn|SP, Rm {,extend {#amount}}と同じ CMN Wn, Wm {,shift #amount} // ADDS WZR, Wn, Wm {,shift #amount}と同じ CMN Xn, Xm {,shift #amount} // ADDS XZR, Xn, Xm {,shift #amount}と同じ
命令エンコード
命令 | 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 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ADD (shifted) | z | 0 | 0 | 0 1 0 1 1 | shift | 0 | Rm | imm6 (0-63) | Rn | Rt | ||||||||||||||||||||||
ADD (imm12) | z | 0 | 0 | 1 0 0 0 1 | shift | imm12 (0-4095) | Rn | Rt | ||||||||||||||||||||||||
ADD (extended) | z | 0 | 0 | 0 1 0 1 1 | 0 0 | 1 | Rm | option | imm3 | Rn | Rt | |||||||||||||||||||||
SUB (shifted) | z | 1 | 0 | 0 1 0 1 1 | shift | 0 | Rm | imm6 (0-63) | Rn | Rt | ||||||||||||||||||||||
SUB (imm12) | z | 1 | 0 | 1 0 0 0 1 | shift | imm12 (0-4095) | Rn | Rt | ||||||||||||||||||||||||
SUB (extended) | z | 1 | 0 | 0 1 0 1 1 | 0 0 | 1 | Rm | option | imm3 | Rn | Rt | |||||||||||||||||||||
ADDS (shifted) | z | 0 | 1 | 0 1 0 1 1 | shift | 0 | Rm | imm6 (0-63) | Rn | Rt | ||||||||||||||||||||||
ADDS (imm12) | z | 0 | 1 | 1 0 0 0 1 | shift | imm12 (0-4095) | Rn | Rt | ||||||||||||||||||||||||
ADDS (extended) | z | 0 | 1 | 0 1 0 1 1 | 0 0 | 1 | Rm | option | imm3 | Rn | Rt | |||||||||||||||||||||
SUBS (shifted) | z | 1 | 1 | 0 1 0 1 1 | shift | 0 | Rm | imm6 (0-63) | Rn | Rt | ||||||||||||||||||||||
SUBS (imm12) | z | 1 | 1 | 1 0 0 0 1 | shift | imm12 (0-4095) | Rn | Rt | ||||||||||||||||||||||||
SUBS (extended) | z | 1 | 1 | 0 1 0 1 1 | 0 0 | 1 | Rm | option | imm3 | Rn | Rt |
キャリー込の加減算
加減算でオーバーフロー (キャリー、桁あふれ) やアンダーフロー (ボロー、桁借り) のために NZCV レジスタの C ビットがキャリーとして使用されます。
アドレッシングモード
キャリー込の加減算のアドレッシングは、単純なレジスタ指定のみです。
アドレッシング | ||||
---|---|---|---|---|
演算 | レジスタ | シフトレジスタ | イミディエート | 拡張レジスタ |
キャリー込み加算 | ADC | |||
キャリー込み加算 | SBC |
キャリー込の加算
キャリーを含めて加算します。 キャリーフラグが 1 のときに 1 が余分に加算されます。 複数のレジスタにわたる(多倍長)加算に使います。
ADC Rd, Rn, Rm ADCS Rd, Rn, Rm
キャリーフラグとキャリー込の減算を試してみます。stdio.sとdebug.sを置いたディレクトリに、次のコードを adc.s というファイル名で作成します。 64ビットの大きな数値(0x8000000000000000) を 2 つ加算して、フラグを表示、0 と 0 をキャリー込み加算して結果を表示するプログラムです。 加算でキャリー (桁あふれ) が発生、「0 + 0 + キャリー」の結果は 1 になると予想されます。
.include "debug.s" .text .global _start _start: mov x1, #0x8000000000000000 adds x0, x1, x1 // x0 = x1 + x1 PRINTFLAGS // print flags adc x0, xzr, xzr // x0 = 0 + 0 bl PrintLeft // print x0 bl NewLine bl Exit
アセンブル、リンク、実行してみます。
as -o adc.o adc.s ld -o adc adc.o ./adc nZCV 1
予想通り、結果は 1 になりました。debug.s の PRINTFLAGS マクロはキャリーフラグが c の場合は 0、C の場合は 1 を表示します。 結果は「C」となっているため キャリーで 「Carry = 1」となることが確認できます。
キャリー込の減算
キャリー(ボロー)を含めて減算します。 キャリーフラグが 0 のときに 1 が余分に引かれます(参考)。複数のレジスタにわたる(多倍長)減算に使います。
SBC Rd, Rn, Rm SBCS Rd, Rn, Rm
キャリーフラグとキャリー込の減算を試してみます。stdio.sとdebug.sを置いたディレクトリに、次のコードを sbc.s というファイル名で作成します。 0 から 1 を引いて、フラグを表示、0 から 0 をキャリー込み減算して結果を表示するプログラムです。 「0 - 1」でボロー (桁借り) が発生、「0 - 0 - ボロー」の結果は -1 になると予想されます。
.include "debug.s" .text .global _start _start: mov x1, #1 subs x0, xzr, x1 // x0 = 0 - 1 PRINTFLAGS // print flags sbc x0, xzr, xzr // x0 = 0 - 0 bl PrintLeft // print x0 bl NewLine bl Exit
アセンブル、リンク、実行してみます。
as -o sbc.o sbc.s ld -o sbc sbc.o ./sbc Nzcv -1
予想通り、結果は -1 です。 debug.s の PRINTFLAGS マクロはキャリーフラグが c の場合は 0、C の場合は 1 を表示します。 結果は「c」となっているため ボローの場合に 「Carry=0」となることが分かります。
命令エンコード
命令 | 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 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ADC | z | 0 | 0 | 1 1 0 1 0 0 0 0 | Rm | 0 0 0 0 0 0 | Rn | Rt | ||||||||||||||||||||||||
ADCS | z | 0 | 1 | 1 1 0 1 0 0 0 0 | Rm | 0 0 0 0 0 0 | Rn | Rt | ||||||||||||||||||||||||
SBC | z | 1 | 0 | 1 1 0 1 0 0 0 0 | Rm | 0 0 0 0 0 0 | Rn | Rt | ||||||||||||||||||||||||
SBCS | z | 1 | 1 | 1 1 0 1 0 0 0 0 | Rm | 0 0 0 0 0 0 | Rn | Rt |
乗算命令
乗算命令は32ビットまたは64ビットの乗算を行います。積和命令 (MADD) は乗算と加算を同時に行う命令で、積差命令(MSUB)は乗算と減算を同時に行う命令です。32ビット同士の乗算でも結果は 32 ビットで返り、64ビット同士の乗算でも結果は 64 ビットで返ります。乗算結果の上位ビットを取得するための命令として、SMULH(符号付)、UMULH(符号なし)という 専用命令が用意されています。下位ビットは符号付き(2の補数)、符号無しのどちらの場合も同じになります。
倍精度積算(multiply long)命令は、32ビットの整数積算を行い、64ビットの結果を返します。積算と積和(64ビット整数の加算も行う)、符号付きと符合無し演算があり、計4種類の命令(UMULL,UMULAL,SMULL,SMULAL)があります。
MADD/MUL
積和(Multiply-Add)演算は演算は2つのレジスタの積 (Rn * Rm) をレジスタ Ra に加算して、結果をレジスタ Rd に格納します。 MUL命令は加算するレジスタを ゼロレジスタにしたMADD命令です。
MADD Wd, Wn, Wm, Wa // Wd = Wa + (Wn * Wm) MADD Xd, Xn, Xm, Xa // Xd = Xa + (Xn * Xm) MUL Wd, Wn, Wm // MADD Wd, Wn, Wm, WZR の別名 MUL Xd, Xn, Xm // MADD Xd, Xn, Xm, XZR の別名
MSUB/MNEG
積差(Multiply-Subtract)演算は2つのレジスタの積 (Rn * Rm) をレジスタ Ra から減算して、結果をレジスタ Rd に格納します。MNEG命令は減算する対象の レジスタをゼロレジスタにしたMSUB命令です。
MSUB Wd, Wn, Wm, Wa // Wd = Wa - (Wn * Wm) MSUB Xd, Xn, Xm, Xa // Xd = Xa - (Xn * Xm) MNEG Wd, Wn, Wm // MSUB Wd, Wn, Wm, WZR の別名 MNEG Xd, Xn, Xm // MSUB Xd, Xn, Xm, XZR の別名
SMULH
符号付上位乗算 (Signed Multiply High) は 2 つの 64 ビットレジスタ Xn と Xm を乗算し、その 128 ビットの乗算結果の上位 64 ビットをレジスタ (Xd) に書き込みます。
SMULH Xd, Xn, Xm
UMULH
符号なし上位乗算 (Unsigned Multiply High) は 2 つの 64 ビットレジスタを乗算し、その 128 ビットの乗算結果の上位 64 ビットをレジスタに書き込みます。
UMULH Xd, Xn, Xm
SMADDL/SMUL
2 つの 32 ビットのレジスタ Wn とWm の積を 64 ビットのレジスタ Xa と加算し、その結果を 64 ビットのレジスタ Xd に書き込みます。
SMADDL Xd, Wn, Wm, Xa
SMULL Xd, Wn, Wm // SMADDL Xd, Wn, Wm, XZR の別名
UMADDL/UMULL
2 つの 32 ビットのレジスタ Wn とWm の積を 64 ビットのレジスタ Xa と加算し、その結果を 64 ビットのレジスタ Xd に書き込みます。
UMADDL Xd, Wn, Wm, Xa
UMULL Xd, Wn, Wm // UMADDL Xd, Wn, Wm, XZR の別名
SMSUBL/SMNEGL
64 ビットのレジスタ Xa から 32ビットレジスタWn とWm の積を減算し、その結果を 64 ビットのレジスタ Xd に書き込みます。
SMSUBL Xd, Wn, Wm, Xa // Xd = Xa - (Wn * Wm) SMNEGL Xd, Wn, Wm // SMSUBL Xd, Wn, Wm, XZR の別名
UMSUBL/UMNEGL
64 ビットのレジスタ Xa から 32ビットレジスタWn とWm の積を減算し、その結果を 64 ビットのレジスタ Xd に書き込みます。
UMSUBL Xd, Wn, Wm, Xa
UMNEGL Xd, Wn, Wm // UMSUBL Xd, Wn, Wm, XZR の別名
命令エンコード
命令 | 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 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MADD | z | 0 0 | 1 1 0 1 1 | 0 0 0 | Rm | 0 | Ra | Rn | Rd | |||||||||||||||||||||||
MUL | z | 0 0 | 1 1 0 1 1 | 0 0 0 | Rm | 1 | 1 1 1 1 1 | Rn | Rt | |||||||||||||||||||||||
MSUB | z | 0 0 | 1 1 0 1 1 | 0 0 0 | Rm | 1 | Ra | Rn | Rd | |||||||||||||||||||||||
MNEG | z | 0 0 | 1 1 0 1 1 | 0 0 0 | Rm | 1 | 1 1 1 1 1 | Rn | Rd | |||||||||||||||||||||||
xMADDL | 1 | 0 0 | 1 1 0 1 1 | U | 0 1 | Rm | 0 | Ra | Rn | Rd | ||||||||||||||||||||||
xMSUBL | 1 | 0 0 | 1 1 0 1 1 | U | 0 1 | Rm | 1 | Ra | Rn | Rd | ||||||||||||||||||||||
xMULH | 1 | 0 0 | 1 1 0 1 1 | U | 1 0 | Rm | 0 | (1 1 1 1 1) | Rn | Rd |
除算命令
除算命令は32ビットまたは64ビットの整数の除算を行います。商はゼロに向かって丸められます。SDIV(符号付整数) と UDIV(符号なし整数)の2つの命令があります。 0 で除算した場合は、エラーとはならず除算結果が 0 となります。
Rd = Rn / Rm
剰余は除算命令では計算されないため、MSUB命令を使って求めます。
mov x2, #37 mov x3, #10 sdiv x0, x2, x3 // x0 = 37 / 10 --> 3 msub x4, x0, x3, x2 // x4 = 37 - 3 * 10 --> 7
SDIV
SDIV は32ビットまたは64ビットの符号付整数の除算を行います。
SDIV Wd, Wn, Wm SDIV Xd, Xn, Xm
最も小さい負の整数を -1 で除算すると符号付整数の範囲を超えますが、オーバーフローは発生せず、最も小さい負の整数がそのまま結果に入ります。 下の例は 64ビットの最も小さい整数 -9223372036854775808 を -1 で割った 場合に 9223372036854775808 にならず、-9223372036854775808 になることを 確認できます。 64 ビットで表現できるもっとも大きい整数 9223372036854775807 より大きくなるためです。
mov x5, #0x8000000000000000 // -9223372036854775808 mov x6, #-1 // -1 sdiv x0, x5, x6 // x0 = -9223372036854775808
32ビットでも同様に -2147483648 を -1 で割ると -2147483648 が返ります。
UDIV
UDIV は32ビットまたは64ビットの符号なし整数の除算を行います。
UDIV Wd, Wn, Wm UDIV Xd, Xn, Xm
命令エンコード
命令 | 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 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SDIV | z | 0 0 | 1 1 0 1 0 1 1 0 | Rm | 0 0 0 0 1 | 1 | Rn | Rd | ||||||||||||||||||||||||
UDIV | z | 0 0 | 1 1 0 1 0 1 1 0 | Rm | 0 0 0 0 1 | 0 | Rn | Rd |
論理演算
アドレッシングモード
論理演算命令のアドレッシングモードには、シフトレジスタ、イミディエート(定数指定)、 拡張レジスタの3種類がありますが、命令によって使えるアドレッシングモードが 異なっているため、注意が必要です。
アドレッシング | |||
---|---|---|---|
演算 | シフトレジスタ | イミディエート | 拡張レジスタ |
論理積 | AND | AND | |
論理積 | ANDS / TST | ANDS / TST | |
ビットクリア | BIC | ||
ビットクリア | BICS | ||
否定論理和 | ORN | ||
論理和 | ORR | ORR | |
否定排他的論理和 | EON | ||
排他的論理和 | EOR | EOR |
イミディエート
汎用レジスタと即値を論理演算して、結果を汎用レジスタまたはスタックポインタに設定します。 即値は、ビットマスク用の32ビットまたは64ビットのパターンを指定できます。 2、4、8、16、32、64ビットを単位として、連続した 0 または 1 のパターンを繰り返した値を指定できます。例えば 0x000000001ffffc00、0xfffffffffc0fffff、0x007f007f007f007f、0x7070707070707070、0x5555555555555555といった即値です。 不可能なパターンを指定するとアセンブラで「Error: immediate out of range at operand 3」というエラーを起こします。
AND Wd|WSP, Wn, #imm AND Xd|SP, Xn, #imm
シフトレジスタ
汎用レジスタ Rn と汎用レジスタ Rm 間の演算を行い、結果を汎用レジスタに格納します。オプションで Rm レジスタの値に対してシフト演算を指定することができます。デフォルトは LSL になり、LSR、ASR、または ROR も指定できます。
AND Wd, Wn, Wm {,shift #amount} AND Xd, Xn, Xm {,shift #amount}
AND
レジスタとレジスタ、またはレジスタと定数のビット単位の論理積を実行して、結果をレジスタに書き込みます。演算結果で条件フラグ (NZCV レジスタ) は変化しません。
AND Wd|WSP, Wn, #imm AND Wd, Wn, Wm {,shift #amount} AND Xd|SP, Xn, #imm AND Xd, Xn, Xm {,shift #amount}
ANDS
レジスタとレジスタ、またはレジスタと定数のビット単位の論理積を実行して、結果をレジスタに書き込みます。演算結果に応じて条件フラグ (NZCV レジスタ) のビットを更新します。
ANDS Wd|WSP, Wn, #imm ANDS Wd, Wn, Wm {,shift #amount} ANDS Xd|SP, Xn, #imm ANDS Xd, Xn, Xm {,shift #amount}
TST
レジスタとレジスタ、またはレジスタと定数のビット単位の論理積を実行して、演算結果に応じて条件フラグ (NZCV レジスタ) のビットを更新します。 この命令はアセンブラで ANDS に翻訳されます。
TST Wn, #imm // ANDS WZR, Xn, #imm と同じ TST Wn, Wm {,shift #amount} // ANDS WZR, Wn, Wm {,shift #amount} と同じ TST Xn, #imm // ANDS XZR, Xn, #imm と同じ TST Xn, Xm {,shift #amount} // ANDS XZR, Xn, Xm {,shift #amount} と同じ
ORR
レジスタとレジスタ、またはレジスタと定数のビット単位の論理和を実行して、結果をレジスタに書き込みます。 演算結果で条件フラグ (NZCV レジスタ) は変化しません。
ORR Wd|WSP, Wn, #imm ORR Wd, Wn, Wm {,shift #amount} ORR Xd|SP, Xn, #imm ORR Xd, Xn, Xm {,shift #amount}
ORN
Rn レジスタの値と、 Rm レジスタを反転した値との間で論理和を求め、 結果を Rd レジスタに書き込みます。オプションで Rm レジスタの値に対して シフト演算を指定することができます。デフォルトは LSL になり、LSR、ASR、 または ROR も指定できます。 演算結果で条件フラグ (NZCV レジスタ) は変化しません。
ORN Xd, Xn, Xm {,shift #amount} ORN Wd, Wn, Wm {,shift #amount}
EOR
レジスタとレジスタ、またはレジスタと定数のビット単位の排他的論理和を実行して、結果をレジスタに書き込みます。 演算結果で条件フラグ (NZCV レジスタ) は変化しません。
EOR Wd|WSP, Wn, #imm EOR Wd, Wn, Wm {,shift #amount} EOR Xd|SP, Xn, #imm EOR Xd, Xn, Xm {,shift #amount}
EON
Rn レジスタの値と、 Rm レジスタを反転した値との間で論理和を求め、 結果を Rd レジスタに書き込みます。オプションで Rm レジスタの値に対して シフト演算を指定することができます。デフォルトは LSL になり、LSR、ASR、 または ROR も指定できます。
EON Xd, Xn, Xm {,shift #amount} EON Wd, Wn, Wm {,shift #amount}
BIC
BIC命令は、ビット単位で指定したビットをクリアします。 Rn レジスタの値と、 Rm レジスタを反転した値との間で論理積を求め、結果を Rd レジスタに書き込みます。演算結果で条件フラグ (NZCV レジスタ) は変化しません。
BIC Wd, Wn, Wm {,shift #amount} BIC Xd, Xn, Xm {,shift #amount}
BICS
BIC命令は、ビット単位で指定したビットをクリアします。 Rn レジスタの値と、 Rm レジスタを反転した値との間で論理積を求め、結果を Rd レジスタに書き込みます。演算結果に応じて条件フラグ (NZCV レジスタ) のビットを更新します。
BICS Wd, Wn, Wm {,shift #amount} BICS Xd, Xn, Xm {,shift #amount}
命令エンコード
命令 | 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 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
AND (shifted) | z | 0 0 | 0 1 0 1 0 | shift | 0 | Rm | imm6 | Rn | Rd | |||||||||||||||||||||||
AND (imm) | z | 0 0 | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd | ||||||||||||||||||||||||
ANDS (shifted) | z | 1 1 | 0 1 0 1 0 | shift | 0 | Rm | imm6 | Rn | Rd | |||||||||||||||||||||||
ANDS (imm) | z | 1 1 | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd | ||||||||||||||||||||||||
ORR (shifted) | z | 0 1 | 0 1 0 1 0 | shift | 0 | Rm | imm6 | Rn | Rd | |||||||||||||||||||||||
ORR (imm) | z | 0 1 | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd | ||||||||||||||||||||||||
ORN (shifted) | z | 0 1 | 0 1 0 1 0 | shift | 1 | Rm | imm6 | Rn | Rd | |||||||||||||||||||||||
EOR (shifted) | z | 1 0 | 0 1 0 1 0 | shift | 0 | Rm | imm6 | Rn | Rd | |||||||||||||||||||||||
EOR (imm) | z | 1 0 | 1 0 0 1 0 0 | N | immr | imms | Rn | Rd | ||||||||||||||||||||||||
EON (shifted) | z | 1 0 | 0 1 0 1 0 | shift | 1 | Rm | imm6 | Rn | Rd | |||||||||||||||||||||||
BIC (shifted) | z | 0 0 | 0 1 0 1 0 | shift | 1 | Rm | imm6 | Rn | Rd | |||||||||||||||||||||||
BICS (shifted) | z | 1 1 | 0 1 0 1 0 | shift | 1 | Rm | imm6 | Rn | Rd |
shift | |
---|---|
function | bit |
LSL | 00 |
LSR | 01 |
ASR | 10 |
ROR | 11 |