AArch32
読み:エイアーキ-さんじゅうに
外語:AArch32
ARMアーキテクチャの実行モードのうち、当初からある32ビットのステート(動作モード)。
概要
ARMアーキテクチャはARMv8から64ビットの仕様が追加されたため、従来の動作をAArch32と呼ぶようになった。
長く使われ、また今後も当分は使われ続ける32ビット仕様のARMアーキテクチャは、RISCを公言しながら、他のRISCにはないCISC的な仕様が多数存在する。
仕様
主な仕様
- 主たる命令セットは2種類、A32(旧来のARM命令)と、T32(Thumb命令)
- オペコードは、A32は32ビット固定長、T32は16ビット単位で16ビットまたは32ビットの可変長
- 汎用レジスターは32ビット長
- 汎用レジスターは16本 (うち3本は専用レジスター兼用)
- 複数レジスターを処理する複雑な命令がある
- 全ての命令が条件付き命令である。Thumb命令でも、Thumb-2命令にはIT命令があり条件が付けられる
- 整数除算命令はない (整数乗算命令はある)
汎用レジスター
汎用レジスターは16本あり、r0〜r15と名前が付いている。うち13本は本当に汎用で、残る3本に特殊な機能が付けられている。
リンクレジスター(lr)は、サブルーチン呼び出し時に、戻るアドレスが保存されるレジスターである。ARMではこのアドレスはスタックに積まれるのではない。リンクレジスターは1つの戻りアドレスしか保持できないので、プログラムで随時スタックへの退避などの処理を書く必要がある。
r15はプログラムカウンター(pc)で、ここに代入すると、そのアドレスにジャンプする。サブルーチンから復帰などは、次のような命令になる。
mov pc, lr
ありきたりのCPUでは「ret」などの命令になるところ、言われてみれば確かにその通りというようなスタイルの書き方になる。なお、次のような命令も別に存在する。
bx lr
動作は同じである。
アドレス空間
AArch32では、従来は32ビットの物理アドレスおよびアドレス空間(4Giバイト)を提供した。
ARM Cortex-A15では拡張され、32ビットの仮想メモリー空間と、40ビットの物理アドレス空間(1Tiバイト)に対応した。
実行できる命令の種類
ベクターテーブル
ARMの割り込みベクターテーブルは、一つが32ビットで7個存在する。
- 0x00000000 リセット (Supervisor)
- 0x00000004 未定義命令 (Undefined)
- 0x00000008 ソフトウェア割り込み(SWI) (Supervisor)
- 0x0000000C プリフェッチ・アボート (Abort)
- 0x00000010 データ・アボート (Abort)
- 0x00000018 IRQ(通常割り込み) (IRQ)
- 0x0000001C FIQ(高速割り込み) (FIQ)
いわゆるアドレスエラーは、命令フェッチ時かデータアクセス時かにより、二つに分けられてアボートが発生する。
特記点
多機能な命令
ARMはRISCだが、それぞれの命令が複雑な機能を持っている。
特に全ての命令に、条件より実行されたり、されなかったりする条件実行機能を有している点は特記に値する。条件分岐はどのようなCPUにもあるが、条件加算、条件減算などの命令は珍しい。
近年のCPUは、パイプラインというCPUが前もって命令を解析することで高速化する機構を持っているが、分岐命令はパイプラインを乱して実行速度を低下させる主要な要因である。ARMでは殆どの命令が条件実行機能を有しているため、条件分岐命令を減らすことが可能となっている。
弱点
多機能で使いやすいCPUであるため、アセンブリ言語によるプログラミングもしやすい。その上で問題となる点としては、次のようなものがある。
- 最大9種類あるアドレッシングモードがやや複雑
- 定数やアドレスをレジスターに設定する場合、8ビット単位でしか行なうことができないため、特殊な技巧が必要
- 整数に対する除算命令が無い (乗算命令はある)
動作
ステート
命令セット
- A32
- T32
- Jazelleステート
- ThumbEEステート … Jazelle RCT(Runtime Compilation Target)とも呼ばれる
A32
実行条件
通常の命令がA32である。64ビット対応型(ARMv8)では、このモードを「AArch32ステート」という。
A32は32ビット固定長で、全ての命令に4ビットの条件フィールドが付いており、無条件を含めて15種類の実行条件を指定することができることを特徴とする。
これは分岐命令だけでなく、加減算や代入などの命令にも適用できることを意味する。つまり、条件を見て特定の式をジャンプする命令を書く代わりに、その特定の式自体に実行条件が付けられる。ジャンプを減らすことは、処理の高速化に繋がる。
全ての命令に付けられる16の条件は、次の通り。
- EQ ‐ 等しい (Z=1)
- NE ‐ 等しくない (Z=0)
- CS/HS ‐ ≧(符号無し) (C=1)
- CC/LO ‐ <(符号無し) (C=0)
- MI ‐ 負 (N=1)
- PL ‐ 正またはゼロ (N=0)
- VS ‐ オーバフロー (V=1)
- VC ‐ オーバフローではない (V=0)
- HI ‐ >(符号無し) (C=1 AND Z=0)
- LS ‐ ≦(符号無し) (C=0 OR Z=1)
- GE ‐ ≧(符号あり) (N=V)
- LT ‐ <(符号あり) (N≠V)
- GT ‐ >(符号あり) (Z=0 AND N=V)
- LE ‐ ≦(符号あり) (Z=1 AND N≠V)
- AL ‐ 無条件
他の条件
命令により、更に追加の条件が付けられるものもある。加減算や比較、論理演算などではSを付けて演算結果をステータスレジスターに入れることが可能なほか、左右のシフトやローテートを組み合わせることが可能(@以降がコメントであるものとする、以下同様)。
addnes r1, r2, r3 LSL #16 @ r1 = r2 + (r3 << 16)
ARMはRISCだが、ここまでを1命令で実行することができる。
また、メモリーとレジスター間の移動(ldr/str)命令は、実行後にレジスターのインクリメント/デクリメントが可能。
ldrb r3, [r0, #+1]! @ r3=*(r0++)
strb r3, [r1, #+1]! @ *(r1++)=r3
Cでありがちな、読み書きしてポインターを増やすような処理を、1命令で実行できる。
ThumbEEステート
Thumb命令セットの変種として、ARMv7-Aプロファイルには搭載必須、ARMv7-Rプロファイルでは搭載任意とされている。
Jazelle(ジャゼール)
ARMv5TEJで、ARMv5TEに対しJavaバイトコードの実行機能として搭載されたもの。
ARMv6からは標準機能となるが、それでもなおJazelle拡張機能として呼ばれることが多い。
しかし現在、Javaバイトコード実行機能はほぼ需要が無い。なぜなら、現在Java言語の主たる用途はAndroid用のプログラミングであり、そしてAndroidで使われているDalvikのバイトコードはJavaバイトコードではないため、そのままではAndroidの高速化に寄与しないからである。
スタック
ハードウェアスタック
ARMには、ハードウェアスタック機能がない。
サブルーチン呼び出しの命令BLは、元のアドレスをR14=LRに保存する。戻るときはLRをR15=PCに書き込めば良い(mov pc, lr)という豪快な仕様である。
スタックはソフトウェア的に実現されており、スタックポインターはR13を標準的に使う。実際はどのレジスターでも良いはずだが、R13〜R15は割り込みなどモードにより自動的にバンク切り替えされるレジスターであるため、R13を使うことが多い。アセンブラーもR13の別名をSPとしている。
挙動
ソフトウェア処理なので動作も変幻自在である。
ARMのアセンブラーでは、A32やT32は、PUSH/POPニーモニックは、原則としてSTM/LDM命令の同等機能のエイリアスとなっている。
例えばA32の場合、レジスター単独のPUSH/POPは次の命令のエイリアスになる。
- PUSH Rt ‐ STR Rt,[SP,#-4]!
- POP Rt ‐ LDR Rt,[SP],#4
複数のレジスターのロードストアは、SPの使い方で、都合4種類がある。
- IB Increment Before ‐ 最初にSPを増分
- IA Increment After ‐ 後でSPを増分
- DB Decrement Before ‐ 最初にSPを減分
- DA Decrement After ‐ 後でSPを減分
一般的なCPUと同じ動きをさせるには、ストアはDB、ロードはIAである。
そこで、SPの動きとは別に動作でも名前が付いている。通常はこちらを使う。
- FD Full Descending (ロードIA、ストアDB)
- ED Empty Descending (ロードIB、ストアDA)
- FA Full Ascending (ロードDA、ストアIB)
- EA Empty Ascending (ロードDB、ストアIA)
使用例
STMFD sp!, { … }
STMED sp!, { … }
STMFA sp!, { … }
STMEA sp!, { … }
ストアしたものは後でロードする前提なので、SPの動きは相互に補完的でなければならない。つまり、一般的なCPUと同じ動きをさせるには、STMFDでpushし、LDMFDでpopする。以下に例を示す(保存するレジスターは一例)。
STMFD SP!,{R0-R7,LR}
(処理)
LDMFD SP!,{R0-R7,PC}
サブルーチンの最初と最後をこのようにすると、自動的にPCにLRが入り、元の処理に戻る。
コプロセッサー
最大16
仕様上、最大16個までのコプロセッサーに対応している。
CP0-CP15のうち、CP14は設定と制御用に予約され、CP15はシステム制御コプロセッサーが登録されている。
CP10とCP11はVFPとAdvanced SIMD(NEON)拡張命令をサポートするために使用されている。
CP0-CP7は、実装定義されたベンダー固有の機能の提供のために使用可能。例えば、XScaleのWireless MMXはCP0とCP1が使用されている。Wireless MMXが2つを使うのは、ARM命令体系において、1コプロセッサーあたり最大16レジスターまでしか指定できないためである。内部が2つのコプロセッサーに分かれているわけではない。
VFP
VFP(Vector Floating Point)は、ARMにおけるコプロセッサー拡張。
単精度および倍精度の実数演算機能を提供する。
- VFPv1
- VFPv1は廃止された。
- VFPv2
- 次に含まれる、オプションの拡張機能である。
- ARMv5TE、ARMv5TEJ、ARMv6、ARMv6KアーキテクチャーのARM命令
- ARMv6T2アーキテクチャーのARM命令とThumb命令
vector modeを特徴としていたが、ARMv7以降は段階的に廃止の方向となった。代わりに、後述するAdvanced SIMD(NEON)が搭載される。
- VFPv3
- 次に含まれる、オプションの拡張機能である。
VFPv3には幾つかのバリエーションがある。
- VFPv3 ‐ 無印はNEON搭載。倍精度レジスターは32本搭載
- VFPv3-FP16 ‐ Cortex-A9以降は、half型(16bit float)変換拡張命令に対応する
- VFPv3-D16 ‐ NEONがなく、倍精度レジスターは半分の16本のみ。D16〜D31にアクセスすると未定義命令例外。VFPv2相当の廉価版
- VFPv4
- 浮動小数点数演算の標準IEEE 754の積和演算(FMA)に対応した。
VFPv4にも幾つかのバリエーションがある。
- VFPv4 ‐ 無印は全機能実装。VFPv3-FP16相当のhalf型(FP16)機能も対応する
- VFPv4-D16 ‐ half型に対応するが、NEONがなく、倍精度レジスターは半分の16本のみの廉価版。D16〜D31にアクセスすると未定義命令例外。Cortex-A5などに存在する
Advanced SIMD
ARMにおける標準のSIMD命令セットで、ARMv7-AとARMv7-Rのオプション仕様である。
その関連する実装およびサポートソフトウェアは「NEON」技術と呼ばれている。
VFPv3と共に実装されている場合、レジスターバンクは共有され、いくつかの共有命令が使用される。
これは、x86でFPUの代わりにSSEが利用できるように、ARMではVFPの代わりにNEONを使うことができる。標準的な実装では、半精度拡張を実装しているのは、VFPv3またはNEONのみ。
再検索