QEMUでRP2350アセンブラプログラミング
RP2350のCPUアーキテクチャ
チップ
RP2350
CPUコア
Cortex-M33
CPUアーキテクチャ
Armv8-Mアーキテクチャ
QEMUの対応状況
Cortex-M33の対応状況を確認。手元のバージョンではサポートされているみたい。
code:sh
$ qemu-system-arm -cpu help
Available CPUs:
...
cortex-m0
cortex-m3
cortex-m33
cortex-m4
cortex-m55
cortex-m7
cortex-r5
cortex-r52
cortex-r5f
...
次に対応ボードを確認。対応ボードにラズピコ系は無さげ。
→ virt で良いかな?
→ virt は cortex-m33 に対応してないとのこと。ChatGPTに聞くと mps2-an505 が良いみたい
→ mps2 まわりの設定は以下が参考になりそう
code:sh
$ qemu-system-arm -machine help
Supported machines are:
...
mps2-an385 ARM MPS2 with AN385 FPGA image for Cortex-M3
mps2-an386 ARM MPS2 with AN386 FPGA image for Cortex-M4
mps2-an500 ARM MPS2 with AN500 FPGA image for Cortex-M7
mps2-an505 ARM MPS2 with AN505 FPGA image for Cortex-M33
mps2-an511 ARM MPS2 with AN511 DesignStart FPGA image for Cortex-M3
mps2-an521 ARM MPS2 with AN521 FPGA image for dual Cortex-M33
mps3-an524 ARM MPS3 with AN524 FPGA image for dual Cortex-M33
mps3-an547 ARM MPS3 with AN547 FPGA image for Cortex-M55
musca-a ARM Musca-A board (dual Cortex-M33)
musca-b1 ARM Musca-B1 board (dual Cortex-M33)
...
raspi0 Raspberry Pi Zero (revision 1.2)
raspi1ap Raspberry Pi A+ (revision 1.1)
raspi2b Raspberry Pi 2B (revision 1.1)
...
virt-8.0 QEMU 8.0 ARM Virtual Machine
virt-8.1 QEMU 8.1 ARM Virtual Machine
virt QEMU 8.2 ARM Virtual Machine (alias of virt-8.2)
virt-8.2 QEMU 8.2 ARM Virtual Machine
...
RP2350のレジスタ
RP2350データシート
汎用レジスタ
R0 〜 R12
R0–R3:引数・戻り値(関数呼び出しで使用)
R4–R11:汎用(callee-saved)
R12:一時用途(scratch register)
フレームポインタ
R11(FP)
スタックポインタ
R13(SP)
リンクレジスタ
R14(LR)
関数戻りアドレスを保持
例外復帰情報も含む
プログラムカウンタ
R15(PC)
浮動小数点レジスタ
(本当?)
S0 〜 S31(単精度)
D0 〜 D15(倍精度として扱う)
FPSCR(ステータス)
https://gyazo.com/637bff13e11c4eecc0bff30e857cec76
https://gyazo.com/79c5b4b09634e32b61aa3d8b88938186
Hello World
まずはアセンブリ言語でHello Worldしてみる。
QEMUで使うcpuとmachine
-cpu は「cortex-m33」
-machine は「mps2-an505」
msp2-an505のメモリマップを確認
code:foo
MEMORY {
RAM (RWX) : ORIGIN = 0x80000000, LENGTH = 0x40000000
}
SECTIONS {
.text : {
*(.text)
_end = .; /* 後日 malloc で使う予定 */
}
}
RP2350でよく使う命令
ARMv8-M(Cortex-M33)の命令は、いわゆる**Thumb-2命令セット(16bit+32bit混在)**が基本です。
ここでは「よく使う基本命令」をカテゴリごとに整理します。
■ 1. データ転送命令
◆ レジスタ間
code:asm
MOV Rd, Rn ; レジスタコピー
MOVS Rd, #imm ; 即値代入(フラグ更新) ◆ メモリロード/ストア
code:asm
◆ バイト・ハーフワード
code:asm
■ 2. 算術演算
code:asm
ADD Rd, Rn, Rm ; 加算
SUB Rd, Rn, Rm ; 減算
MUL Rd, Rn, Rm ; 乗算
フラグ付き
code:asm
ADDS Rd, Rn, Rm
SUBS Rd, Rn, Rm
👉 S付きはxPSRフラグ更新
■ 3. 論理演算
code:asm
AND Rd, Rn, Rm
ORR Rd, Rn, Rm
EOR Rd, Rn, Rm ; XOR
BIC Rd, Rn, Rm ; ビットクリア
MVN Rd, Rn ; NOT
■ 4. シフト・ビット操作
code:asm
■ 5. 比較
code:asm
CMP Rn, Rm
TST Rn, Rm ; ANDしてフラグ更新
👉 結果は保存せずフラグのみ更新
■ 6. 分岐命令
◆ 無条件分岐
code:asm
B label
◆ 条件分岐
code:asm
BEQ label ; == (Z=1)
BNE label ; !=
BGT label ; >
BLT label ; <
👉 条件はxPSRフラグ依存
◆ 関数呼び出し
code:asm
BL func ; Branch with Link
BX LR ; 戻る
■ 7. スタック操作
code:asm
PUSH {R0-R3, LR}
POP {R0-R3, PC}
👉 Cortex-Mでは超重要
■ 8. システム命令
code:asm
NOP ; 何もしない
WFI ; 割り込み待ち(省電力)
WFE ; イベント待ち
SEV ; イベント送信
■ 9. 特殊レジスタ操作
code:asm
MRS Rd, CONTROL ; 特殊レジスタ → 汎用
MSR CONTROL, Rd ; 汎用 → 特殊
例:
code:asm
MRS R0, PRIMASK
MSR PRIMASK, R0
■ 10. 例外・割り込み系
code:asm
■ 11. バリア命令(重要)
code:asm
DMB ; データメモリバリア
DSB ; データ同期バリア
ISB ; 命令同期バリア
👉 デバイス制御で必須
■ 12. ARMv8-M特有(TrustZone)
code:asm
SG ; Secure Gateway
BXNS Rm ; Non-secure branch
BLXNS Rm
👉 セキュア/ノンセキュア切替
■ まとめ(最小セット)
実務でまず覚えるべきはこれ:
MOV / LDR / STR
ADD / SUB
CMP + Bxx
PUSH / POP
BL / BX
👉 これだけでほぼC言語は書ける
■ 補足(重要な理解)
命令長:16bit or 32bit(Thumb-2)
レジスタ:R0–R15
フラグ:xPSRで管理
ロード/ストア型アーキテクチャ
もし興味あれば:
「GCCが出す実際のアセンブリ」
「関数呼び出し規約(ABI)」
「割り込みハンドラの実体」
あたりはかなり理解が深まるのでおすすめです 👍