演算命令は四則演算、論理演算、比較などを行う命令群
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}