モノトーンの伝説日記

Apex Legends, Splatoon, Programming, and so on...

Cortex-M33 (ARMv8-M) ISA 概要

 注意事項必読。

 Raspberry Pi Pico 2 などの RP2350 系向け (他のマイコンに関しては確認していません)。Main Extension も含めすべて使えます。

0. 注意事項

  1. AI を使ってリファレンスから整理させています。
  2. 私が確認した上で公開していますが、間違いや不足する情報などがある可能性があります。
  3. 表にあるサイクル数は Cortex-M33 のものであり、Cortex-M23 ではありません。また、サイクル数に関しては ARM Cortex-M33 Devices Generic User Guide を参照していますが、間違っているケースがあるかもしれません。

1. データ処理命令 (Data Processing Instructions)

1.1 基本算術演算

命令 説明 サイクル数
(Cortex-M33)
補足
ADD, ADDS 2つのオペランドを加算します 1 S付きはAPSRフラグを更新します。
SUB, SUBS 2つのオペランドを減算します 1 S付きはAPSRフラグを更新します。
ADC, ADCS キャリーフラグを含めて加算します 1 多倍長演算に使用します。S付きはフラグを更新。
SBC, SBCS キャリーフラグをボローとして減算します 1 多倍長演算に使用します。S付きはフラグを更新。
RSB, RSBS オペランドを逆にして減算します 1 S付きはフラグを更新します。
CMP 2つのオペランドを比較(減算)し、フラグを更新します 1 結果は破棄されます。
CMN 2つのオペランドを比較(加算)し、フラグを更新します 1 結果は破棄されます。
NEG, NEGS オペランドの符号を反転します (0 - value) 1 RSB Rd, Rn, #0 のエイリアスです。

1.2 乗算・除算

命令 説明 サイクル数
(Cortex-M33)
補足
MUL, MULS 32bit x 32bit乗算を行い、結果の下位32bitを返します 1 S付きはフラグを更新します
MLA 乗算後、第3オペランドを加算します (a * b + c) 1
MLS 乗算後、第3オペランドを減算します (c - a * b) 1
UMULL 符号なし32bit x 32bit乗算を行い、64bitの結果を返します 3 結果は2つのレジスタに格納されます
SMULL 符号付き32bit x 32bit乗算を行い、64bitの結果を返します 3 結果は2つのレジスタに格納されます
UDIV 符号なし32bit除算を行います 2-11 オペランドの値によってサイクル数が変動します
SDIV 符号付き32bit除算を行います 2-11 オペランドの値によってサイクル数が変動します

1.3 論理・シフト演算

命令 説明 サイクル数
(Cortex-M33)
補足
AND, ANDS ビット単位の論理積を計算します 1 S付きはフラグを更新
ORR, ORRS ビット単位の論理和を計算します 1 S付きはフラグを更新
EOR, EORS ビット単位の排他的論理和を計算します 1 S付きはフラグを更新
BIC, BICS ビットクリア(第2オペランドの反転と論理積)を行います 1 S付きはフラグを更新
TST 論理積を計算し、フラグのみ更新します 1 結果は破棄されます
MOV, MOVS レジスタまたは即値をコピーします 1 S付きはフラグを更新
MVN, MVNS レジスタまたは即値をビット反転してコピーします 1 S付きはフラグを更新
LSL, LSLS 論理左シフト 1 S付きはフラグを更新
LSR, LSRS 論理右シフト 1 S付きはフラグを更新
ASR, ASRS 算術右シフト(符号ビットを維持) 1 S付きはフラグを更新
ROR, RORS 右ローテート 1 S付きはフラグを更新

1.4 ビットフィールド・バイト操作

命令 説明 サイクル数
(Cortex-M33)
補足
BFC ビットフィールドをクリアします 1 Main Extension
BFI ビットフィールドに値を挿入します 1 Main Extension
SBFX 符号付きビットフィールドを抽出します 1 Main Extension
UBFX 符号なしビットフィールドを抽出します 1 Main Extension
REV 32bitワード内のバイト順序を反転します 1
REV16 32bitワード内の各16bitハーフワードのバイト順序を反転します 1
REVSH 16bitハーフワードのバイト順序を反転し、符号拡張します 1
RBIT 32bitワード内のビット順序を反転します 1 Main Extension
CLZ 先行するゼロの数(最上位ビットからの連続した0の数)をカウントします 1

2. メモリアクセス命令 (Memory Access Instructions)

命令 説明 サイクル数
(Cortex-M33)
補足
LDR メモリから32bitワードをロードします 2+
LDRH メモリから16bitハーフワードを符号なしでロードします 2+
LDRSH メモリから16bitハーフワードを符号付きでロードします 2+
LDRB メモリから8bitバイトを符号なしでロードします 2+
LDRSB メモリから8bitバイトを符号付きでロードします 2+
STR メモリへ32bitワードをストアします 2+
STRH メモリへ16bitハーフワードをストアします 2+
STRB メモリへ8bitバイトをストアします 2+
LDM, LDMIA, LDMDB 複数のレジスタをメモリからロードします (n+1)+ nはレジスタ数。POPのエイリアスとしても使用
STM, STMIA, STMDB 複数のレジスタをメモリへストアします (n+1)+ nはレジスタ数。PUSHのエイリアスとしても使用
LDREX, LDREXH, LDREXB 排他アクセス用のロード 2+ セマフォなどの排他制御に使用
STREX, STREXH, STREXB 排他アクセス用のストア。成功/失敗を返します 2+
CLREX 排他アクセスモニタをクリアします 1

3. 分岐命令 (Branch Instructions)

命令 説明 サイクル数
(Cortex-M33)
補足
B 指定ラベルへ分岐します 1-3
B<cond> 条件付きで分岐します (e.g., BEQ, BNE) 1-3
BL 戻りアドレスをLRに格納して分岐(サブルーチンコール) 1-3
BLX レジスタ指定アドレスへ分岐し、LRにリターンアドレスを格納 1-3
BX レジスタ指定アドレスへ分岐します 1-3 MOV PC, Rmのエイリアス
CBZ レジスタが0なら分岐します 1-3 フラグに影響しません
CBNZ レジスタが0でないなら分岐します 1-3 フラグに影響しません
IT If-Then命令ブロック。最大4つの後続命令を条件付きで実行 1 非推奨: ARMv8-Aでは廃止。v8-Mでは互換性のために残存
TBB, TBH テーブル分岐。ジャンプテーブルを用いて分岐します 3+ Main Extension

4. システム・その他命令

命令 説明 サイクル数
(Cortex-M33)
補足
SVC スーパーバイザコール例外を発生させます 3+ OSのサービス呼び出しに使用。
MRS 特殊レジスタから汎用レジスタへ値を移動します 1-2
MSR 汎用レジスタから特殊レジスタへ値を移動します 1-2
CPSIE i, CPSID i PRIMASKレジスタを操作し、割り込みを有効/無効化します 2
CPSIE f, CPSID f FAULTMASKレジスタを操作し、フォールトを有効/無効化します 2
WFI 割り込みを待機して低電力モードに入ります 実装依存
WFE イベントを待機して低電力モードに入ります 実装依存
SEV マルチコアシステムでイベントを送信します 1
ISB 命令同期バリア。パイプラインをフラッシュします 3
DSB データ同期バリア。メモリ操作の完了を待ちます 実装依存
DMB データメモリバリア。メモリアクセスの順序を保証します 実装依存
NOP 何も行いません(No Operation) 1
BKPT ブレークポイント例外を発生させます 3+ デバッグ用。

5. DSP拡張命令

5.1 SIMD (Single Instruction, Multiple Data) 演算命令

命令 説明 サイクル数
(Cortex-M33)
補足
SADD8, UADD8 4組の8bitデータに対して並列に符号付き/符号なし加算を行います 1 APSRのGE[3:0]フラグに各レーンのキャリー/ボローがセットされます
SSUB8, USUB8 4組の8bitデータに対して並列に符号付き/符号なし減算を行います 1 APSRのGE[3:0]フラグに各レーンのキャリー/ボローがセットされます
SADD16, UADD16 2組の16bitデータに対して並列に符号付き/符号なし加算を行います 1 APSRのGE[1:0]フラグに各レーンのキャリー/ボローがセットされます
SSUB16, USUB16 2組の16bitデータに対して並列に符号付き/符号なし減算を行います 1 APSRのGE[1:0]フラグに各レーンのキャリー/ボローがセットされます
SASX, UASX 2組の16bitデータをクロスして加算/減算します (e.g., Rd.H0=Rn.H0+Rm.H1) 1 GEフラグが更新されます。ASX = Add and Subtract with Exchange.
SSAX, USAX 2組の16bitデータをクロスして減算/加算します (e.g., Rd.H0=Rn.H0-Rm.H1) 1 GEフラグが更新されます。SAX = Subtract and Add with Exchange.
SHADD8, UHADD8 4組の8bitデータを並列加算し、結果を1/2にします(右シフト) 1 平均化処理に利用します
SHADD16, UHADD16 2組の16bitデータを並列加算し、結果を1/2にします(右シフト) 1 平均化処理に利用します
SHSUB8, UHSUB8 4組の8bitデータを並列減算し、結果を1/2にします(右シフト) 1
SHSUB16, UHSUB16 2組の16bitデータを並列減算し、結果を1/2にします(右シフト) 1
SEL APSRのGEフラグに基づき、2つのソースレジスタのバイトを選択して結合します 1 SIMD演算後のバイト選択に利用します

5.2 サチュレーション(飽和)演算命令

命令 説明 サイクル数
(Cortex-M33)
補足
QADD 符号付き飽和加算を行います 1
QSUB 符号付き飽和減算を行います 1
QADD8, UADD8 4組の8bitデータに対して並列に符号付き/符号なし飽和加算を行います 1
QSUB8, USUB8 4組の8bitデータに対して並列に符号付き/符号なし飽和減算を行います 1
QADD16, UADD16 2組の16bitデータに対して並列に符号付き/符号なし飽和加算を行います 1
QSUB16, USUB16 2組の16bitデータに対して並列に符号付き/符号なし飽和減算を行います 1
QASX, UQASX 2組の16bitデータをクロスして符号付き/符号なし飽和加算/減算を行います 1
QSAX, UQSAX 2組の16bitデータをクロスして符号付き/符号なし飽和減算/加算を行います 1
SSAT 符号付き値を指定したビット幅に飽和させます 1
USAT 符号なし値を指定したビット幅に飽和させます 1

5.3 乗算・積和演算 (MAC) 命令

命令 説明 サイクル数
(Cortex-M33)
補足
SMLAD 2組の16bit乗算を並列で行い、その2つの結果と第3オペランド(アキュムレータ)を加算します 1 Rd = Ra + (Rn.H0*Rm.H0) + (Rn.H1*Rm.H1)
SMLADX SMLADの片方のオペランドを交換したバージョンです 1 Rd = Ra + (Rn.H0*Rm.H1) + (Rn.H1*Rm.H0)
SMLSD 2組の16bit乗算を並列で行い、片方を加算、もう片方を減算します 1 Rd = Ra + (Rn.H0*Rm.H0) - (Rn.H1*Rm.H1)
SMLSDX SMLSDの片方のオペランドを交換したバージョンです 1 Rd = Ra + (Rn.H0*Rm.H1) - (Rn.H1*Rm.H0)
SMLALD SMLADの64bitアキュムレータ版です 3 結果は2つのレジスタに格納されます
SMLALDX SMLADXの64bitアキュムレータ版です 3
SMLSLD SMLSDの64bitアキュムレータ版です 3
SMLSLDX SMLSDXの64bitアキュムレータ版です 3
SMULBB, SMULBT, SMULTB,SMULTT` 2つのレジスタの下位/上位16bitを選択して符号付き16x16乗算を行います 1
SMUAD 2組の16bit乗算を並列で行い、その2つの結果を加算します 1 アキュムレーションなし
SMUADX SMUADのオペランド交換版です 1
SMUSD 2組の16bit乗算を並列で行い、片方からもう片方を減算します 1
SMUSDX SMUSDのオペランド交換版です 1
SMMUL 32x32bit乗算を行い、結果の上位32bitを返します(丸め付き) 1 Q1.31形式などの小数演算に利用

5.4 パッキング・アンパッキング・拡張命令

命令 説明 サイクル数
(Cortex-M33)
補足
PKHBT 2つのレジスタから、片方の下位16bitと、もう片方の上位16bitを結合します 1
PKHTB 2つのレジスタから、片方の上位16bitと、もう片方の下位16bitを結合します 1
SXTAB 8bit値を符号拡張して32bitにし、別の値に加算します 1
SXTAH 16bit値を符号拡張して32bitにし、別の値に加算します 1
SXTB16 2組の8bit値をそれぞれ16bitに符号拡張します 1
UXTAB 8bit値をゼロ拡張して32bitにし、別の値に加算します 1
UXTAH 16bit値をゼロ拡張して32bitにし、別の値に加算します 1
UXTB16 2組の8bit値をそれぞれ16bitにゼロ拡張します 1

6. FPU拡張命令

6.1 データ転送命令 (Load/Store/Move)

命令 説明 サイクル数
(Cortex-M33)
補足
VLDR メモリからFPUレジスタ(S0-S31)に単精度データをロードします 2+ メモリのウェイト数に応じて増加します
VSTR FPUレジスタの単精度データをメモリにストアします 2+ メモリのウェイト数に応じて増加します
VLDM メモリから複数のFPUレジスタをロードします (n+1)+ nはレジスタ数
VSTM 複数のFPUレジスタをメモリにストアします (n+1)+ nはレジスタ数
VMOV FPUレジスタ間、または汎用レジスタとFPUレジスタ間でデータを移動します 1 VMOV.F32 Sd, SmVMOV Rd, Sn など

6.2 算術演算命令 (Arithmetic Instructions)

命令 説明 サイクル数
(Cortex-M33)
補足
VADD.F32 2つの単精度浮動小数点数を加算します 1
VSUB.F32 2つの単精度浮動小数点数を減算します 1
VMUL.F32 2つの単精度浮動小数点数を乗算します 1
VNMUL.F32 2つの単精度浮動小数点数を乗算し、結果の符号を反転します 1 VNEG(VMUL) と同等
VDIV.F32 2つの単精度浮動小数点数を除算します 14 FPU命令の中で最も時間のかかる処理の一つです
VSQRT.F32 単精度浮動小数点数の平方根を計算します 14 VDIV と同様に、完了まで多くのサイクルを要します
VMLA.F32 乗算と加算を結合した演算を行います (a + (b * c)) 1 Fused MAC。VADDVMUL を個別に行うより高精度・高速です。レイテンシは3サイクル
VMLS.F32 乗算と減算を結合した演算を行います (a - (b * c)) 1 Fused MAC。レイテンシは3サイクル
VNMLA.F32 VMLA の結果の符号を反転します 1
VNMLS.F32 VMLS の結果の符号を反転します 1
VABS.F32 単精度浮動小数点数の絶対値を取得します 1
VNEG.F32 単精度浮動小数点数の符号を反転します 1

6.3 変換命令 (Conversion Instructions)

命令 説明 サイクル数
(Cortex-M33)
補足
VCVT.S32.F32 単精度浮動小数点数を符号付き32bit整数に変換します 1 丸めモードはFPSCRで設定できます
VCVT.U32.F32 単精度浮動小数点数を符号なし32bit整数に変換します 1
VCVT.F32.S32 符号付き32bit整数を単精度浮動小数点数に変換します 1
VCVT.F32.U32 符号なし32bit整数を単精度浮動小数点数に変換します 1

(注: Cortex-M33はFPv5-SPのため、半精度 (F16) や倍精度 (F64) へのハードウェア変換命令は通常サポートされません)

6.4 比較命令 (Comparison Instructions)

命令 説明 サイクル数
(Cortex-M33)
補足
VCMP.F32 2つの単精度浮動小数点数を比較します 1 結果はAPSRではなく、FPSCRの条件フラグにセットされます
VCMPE.F32 VCMP と同様ですが、NaNをオペランドに持つ場合に例外を発生させます 1

VCMP命令実行後の注意点:

VCMP命令の結果を使って条件分岐を行うには、VCMP の直後に必ず VMRS APSR_nzcv, FPSCR 命令を実行し、FPUのステータスを汎用レジスタのフラグ(APSR)にコピーする必要があります。その後で B<cond> 命令を使用します。

VCMP.F32  S0, S1            @ S0S1を比較 -> 結果はFPSCRVMRS      APSR_nzcv, FPSCR  @ FPSCRのフラグをAPSRにコピー
BEQ       equal_label       @ APSRを読んで条件分岐