演算命令は四則演算、論理演算、比較などを行う命令群
ARM64では演算命令に3つのレジスタを指定することができる
add x1, x2, x3 // x1 = x2 + x3 add x1, x1, x1 // x1 = x1 + x1 = x1 * 2 add x1, x2, x3 LSL #20 // x1 = x2 + (x3 << 20)
加減算の命令のアドレッシングモードには、単純なレジスタ指定、シフトレジスタ、イミディエート(定数指定)、 拡張レジスタの4種類があり、命令によって使えるアドレッシングが異なる
イミディエート(定数指定)
ADD Xd, Xn, #uimm12 {, LSL #12} ADD Wd, Wn, #uimm12 {, LSL #12}
シフトレジスタ(シフト済みレジスタ指定)
ADD Xd, Xn, Xm {, shift #amount} ADD Wd, Wn, Wm {, shift #amount}
拡張レジスタ
ADD Xd, Xn, Wm {,extend {#amount}} ADD Xd, Xn, Xm {,extend {#amount}}
拡張するデータはbyte, halfword, word, doublewordが可能
### 加減算
Add
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
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
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
NEG Xd, Xm {,shift #amount} // SUB Xd, XZR, Xm {,shift #amount} と同じ NEG Wd, Wm {,shift #amount} // SUB Xd, WZR, Xm {,shift #amount} と同じ
SUBS
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
NEGS Xd, Xm {,shift #amount} // SUBS Xd, XZR, Xm {,shift #amount} と同じ NEGS Wd, Wm {,shift #amount} // SUBS Wd, WZR, Wm {,shift #amount} と同じ
CMP
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
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}と同じ
### キャリー込みの加減算
加減算でオーバーフロー (キャリー、桁あふれ) やアンダーフロー (ボロー、桁借り) のために NZCV レジスタの C ビットがキャリーとして使用される
キャリーを含めて加算。 キャリーフラグが 1 のときに 1 が余分に加算される
ADC Rd, Rn, Rm ADCS Rd, Rn, Rm
キャリーフラグとキャリー込の減算例
.include "debug.s" .text .global _start _start: mov x1, #0x8000000000000000 adds x0, x1, x1 PRINTFLAGS adc x0, xzr, xzr bl PrintLeft bl NewLine bl Exit
$ ld -o test test.o
$ ./test
nZCV
1
キャリー込みの減算
SBC Rd, Rn, Rm SBCS Rd, Rn, Rm
.include "debug.s" .text .global _start _start: mov x1, #1 subs x0, xzr, x1 PRINTFLAGS sbc x0, xzr, xzr bl PrintLeft bl NewLine bl Exit
$ ./test
Nzcv
-1
### 乗算命令
32または64ビットの乗算
MADD/MUL : 2つのレジスタの積 (Rn * Rm) をレジスタ Ra に加算して、結果をレジスタ Rd に格納
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 に格納
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 の別名
### 除算命令
Rd = Rn / Rm 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 Wd, Wn, Wm SDIV Xd, Xn, Xm mov x5, #0x8000000000000000 // -9223372036854775808 mov x6, #-1 // -1 sdiv x0, x5, x6 // x0 = -9223372036854775808
UDIV
UDIV Wd, Wn, Wm UDIV Xd, Xn, Xm
論理演算
論理演算命令のアドレッシングモードには、シフトレジスタ、イミディエート(定数指定)、 拡張レジスタの3種類がある。命令によって使えるアドレッシングモードが異なる。
AND
AND Wd|WSP, Wn, #imm AND Xd|SP, Xn, #imm AND Wd, Wn, Wm {,shift #amount} AND Xd, Xn, Xm {,shift #amount}
ANDS
ANDS Wd|WSP, Wn, #imm ANDS Wd, Wn, Wm {,shift #amount} ANDS Xd|SP, Xn, #imm ANDS Xd, Xn, Xm {,shift #amount}
TST
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 : レジスタとレジスタ、またはレジスタと定数のビット単位の論理和を実行
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 レジスタに書き込み
ORN Xd, Xn, Xm {,shift #amount} ORN Wd, Wn, Wm {,shift #amount}
EOR: レジスタとレジスタ、またはレジスタと定数のビット単位の排他的論理和を実行
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 レジスタを反転した値との間で論理和
EON Xd, Xn, Xm {,shift #amount} EON Wd, Wn, Wm {,shift #amount}
BIC: BIC命令は、ビット単位で指定したビットをクリア
BIC Wd, Wn, Wm {,shift #amount} BIC Xd, Xn, Xm {,shift #amount}
BICS: Rn レジスタの値と、 Rm レジスタを反転した値との間で論理積を求め、結果を Rd レジスタに書き込み
BICS Wd, Wn, Wm {,shift #amount} BICS Xd, Xn, Xm {,shift #amount}