ア | イ | ウ | エ | オ |
カ | キ | ク | ケ | コ |
サ | シ | ス | セ | ソ |
タ | チ | ツ | テ | ト |
ナ | ニ | ヌ | ネ | ノ |
ハ | ヒ | フ | ヘ | ホ |
マ | ミ | ム | メ | モ |
ヤ | ユ | ヨ | ||
ラ | リ | ル | レ | ロ |
ワ | ヰ | ヴ | ヱ | ヲ |
ン |
A | B | C | D | E |
F | G | H | I | J |
K | L | M | N | O |
P | Q | R | S | T |
U | V | W | X | Y |
Z | 数字 | 記号 |
ARMアーキテクチャの実行モードのうち、当初からある32ビットのステート(動作モード)。
汎用レジスターは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個存在する。
いわゆるアドレスエラーは、命令フェッチ時かデータアクセス時かにより、二つに分けられてアボートが発生する。
ARMはRISCだが、それぞれの命令が複雑な機能を持っている。
特に全ての命令に、条件より実行されたり、されなかったりする条件実行機能を有している点は特記に値する。条件分岐はどのようなCPUにもあるが、条件加算、条件減算などの命令は珍しい。
近年のCPUは、パイプラインというCPUが前もって命令を解析することで高速化する機構を持っているが、分岐命令はパイプラインを乱して実行速度を低下させる主要な要因である。ARMでは殆どの命令が条件実行機能を有しているため、条件分岐命令を減らすことが可能となっている。
多機能で使いやすいCPUであるため、アセンブリ言語によるプログラミングもしやすい。その上で問題となる点としては、次のようなものがある。
通常の命令がA32である。64ビット対応型(ARMv8)では、このモードを「AArch32ステート」という。
A32は32ビット固定長で、全ての命令に4ビットの条件フィールドが付いており、無条件を含めて15種類の実行条件を指定することができることを特徴とする。
これは分岐命令だけでなく、加減算や代入などの命令にも適用できることを意味する。つまり、条件を見て特定の式をジャンプする命令を書く代わりに、その特定の式自体に実行条件が付けられる。ジャンプを減らすことは、処理の高速化に繋がる。
全ての命令に付けられる16の条件は、次の通り。
命令により、更に追加の条件が付けられるものもある。加減算や比較、論理演算などでは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命令で実行できる。
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は次の命令のエイリアスになる。
複数のレジスターのロードストアは、SPの使い方で、都合4種類がある。
一般的なCPUと同じ動きをさせるには、ストアはDB、ロードはIAである。
そこで、SPの動きとは別に動作でも名前が付いている。通常はこちらを使う。
使用例
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個までのコプロセッサーに対応している。
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(Vector Floating Point)は、ARMにおけるコプロセッサー拡張。
単精度および倍精度の実数演算機能を提供する。
次に含まれる、オプションの拡張機能である。
vector modeを特徴としていたが、ARMv7以降は段階的に廃止の方向となった。代わりに、後述するAdvanced SIMD(NEON)が搭載される。
次に含まれる、オプションの拡張機能である。
VFPv3には幾つかのバリエーションがある。
浮動小数点数演算の標準IEEE 754の積和演算(FMA)に対応した。
VFPv4にも幾つかのバリエーションがある。
コメントなどを投稿するフォームは、日本語対応時のみ表示されます