アキュムレータと汎用レジスタ
アキュムレータマシンとレジスタマシンという言葉を聞いたことがありますでしょうか?
マイコンの起源はアキュムレータマシンです。CPUの演算時に使用するデータを、アキュムレータと呼ばれるレジスタに一時的に格納する方式です。レジスタはアキュムレータが一つしかありませんから、演算のもう一方のデータはメモリ(または、周辺モジュール)になります。演算結果は、再びアキュムレータに格納され、次の演算に使われます。このようにアキュムレータ方式のCPUをアキュムレータマシンと呼びます。(アキュムレータと言う名前は、accumulate(累算する)に由来しています。)
これとは違いレジスタマシンでは、汎用レジスタと呼ばれるレジスタ群を持っており、演算するデータはレジスタ群の中の任意のレジスタに格納することができます。演算結果を格納するレジスタも、レジスタ群の中の任意のレジスタを選ぶことができます。
演算用のレジスタを多く持っているレジスタマシンの方が、演算を効率的に実行することができるのは明白です。しかしアキュムレータマシンはハードウェアが軽くて済むので、安価なマイコンに向いています。Cortex-M3は高性能を追求したCPUですので、レジスタマシンです。複数のレジスタを持っており、これらのレジスタをデータ処理用に使ったり、間接的にメモリのアドレス指定に使うことができます。
Cortex-M3のレジスタ
Cortex-M3プロセッサは、汎用レジスタの他に特殊レジスタを持っています。特殊レジスタは主に割り込みの処理や設定に使われます。純粋にデータ処理や間接アドレッシングに使うレジスタは13本です。その他に、プログラムカウンタ(PC)、リンクレジスタ(LR)、スタックポインタ(SP)があります。
特殊レジスタには、プログラムステータスレジスタ(xPSR)と、割り込みマスクレジスタのPRIMASK、FAULTMASK、BASEPRIと、制御レジスタのCONTROLがあります。詳細は後の章で説明しますが、ここでは簡単に各レジスタの説明をしておきます。
汎用レジスタR0~R12
データ処理や間接アドレッシングに用います。
スタックポインタ(SP)R13
スタックの場所を示します。
リンクレジスタ(LR)R14
サブルーチン(関数が呼ばれた)の場合の、戻り先アドレスが入ります。
プログラムカウンタ(PC)R15
現在実行されている命令のアドレスを指します。
プログラムステータスレジスタ(xPSR)
Cortex-M3の状態を示します。内部は3つに分かれています。演算結果の状態(ゼロ、負値等々)を示すアプリケーションPSR、割り込みの状態を示す割り込みPSR、Thumb-2命令の実行状態を示す実行PSRです。
割り込みマスクレジスタ(PRIMASK、FAULTMASK、BASEPRI)
割り込み(例外)を無効にするために使います。
制御レジスタ(CONTROL)
特権レベルとスタックポインタの選択を行うために使います。
個別のレジスタのスタッキング
スタックの章で、すべての汎用レジスタがスタックされるわけではないと、述べましたが、PUSH、POP命令を使うと任意のレジスタをスタックすることができます。例えば、以下のように記述すれば、一つの命令で複数のレジスタのPUSH、POPができます。
PUSH { R3-5 , R11 }
:R3,R4,R5,R11をスタックします
POP { R3-5 , R11 }
:R3,R4,R5,R11をスタックから戻します
汎用レジスタ
個人的な話で恐縮ですが、初めて扱ったマイコンがモトローラのMC68000だったので、汎用レジスタ方式が当たり前だと思っていました。(当時、Armはまだありません)
でも、勉強を進めて行くと、アキュムレータ方式がマイコンのオリジナルだとわかって、意外だったのを覚えています。 最近はプログラムをC言語で書くので、アキュムレータか汎用レジスタかを、ユーザはあまり気にせず使えます。アセンブラでプログラムを作っているころは、「このデータをR1に入れて、次にR2と足し算して…」のように汎用レジスタの使い分けを考えながらプログラムを作っていました。C言語になって、とても便利になりましたね。
MC68000の汎用レジスタは全部で16本あってCortex-M3と同じような使い方をするのですが、MC68000の汎用レジスタには役割分担があって、D0~7はデータ用、A0~7はアドレッシング用等々の使い方の制限がありました。しかし、Cortex-M3の汎用レジスタは、データ用、アドレッシング用のような制限事項はありません。どのレジスタも、どちらの用途でも使えます。
また、レジスタは色々な機能を持ったレジスタがあると便利な面もありますが、複雑で使い難い面もあります。従来のArmのレジスタを下図に示します。Cortex-M3では、非常に簡素化されているのがわかります。レジスタ構成が簡単だと、コンパイラも変数の割り当てが簡単になるので、有利と言えます。
下位レジスタ、上位レジスタ
プロセッサには、32ビットの汎用レジスタが13個あります。R0~R12です。アーキテクチャで定義された特別な使用方法はありません。汎用レジスタを指定する大部分の命令は、R0~R12を使用できます。R0~R7を下位レジスタ、R8~R12を上位レジスタと呼んでいます。
- 下位レジスタ
- R0~R7は、汎用レジスタを指定するすべての命令(すなわちThumb-2命令の中の16bit命令、32bit命令)でアクセス可能です。
- 上位レジスタ
- R8~R12は、汎用レジスタを指定するすべての32ビット命令によってアクセス可能です。しかし下位レジスタと異なって、16ビット命令ではアクセスできません。初期値は不定です。
R13(スタックポインタ SP)
R13はスタックポインタです。これはスタックの章で詳しく説明しましたので、ここでは省略します。
R14(リンクレジスタ LR)
レジスタ R14は、サブルーチンとリンクするためのリンクレジスタ(LR)です。LR は、リンク付き分岐(BL)またはリンク付き分岐と状態遷移(BLX)命令が実行されると、PCから復帰アドレスを受け取ります。LRは例外復帰にも使用されます。例えば、C言語上で関数を作るとサブルーチンが作られます。このような時にR14は大活躍します。それ以外の場合は、R14を汎用レジスタとして使用できます。
R15(プログラムカウンタ PC)
R15はプログラムカウンタ(PC)です。実行している命令のアドレスを指します。Cortex-M3は3段パイプラインです。フェッチ、デコード、実行の3段の処理を並列して行い、見かけ上1命令1サイクルで実行しています。PCは3段パイプラインの中のデコードを処理している命令のアドレスを指します。
様々なマイコンの汎用レジスタ
マイコンによってレジスタ構成は色々異なります。Cortex-M3の場合、データレジスタとアドレスレジスタの区分けはないので、R0~R12をどちらの用途でも自由に使えます。しかし、マイコンによっては、データレジスタとアドレスレジスタを分けているものがあります。また、アキュムレータ方式なのにアドレスレジスタを持っているマイコンもあります。レジスタ構成はそのマイコン(CPU)の個性を最も現している仕様だと思います。逆に汎用レジスタの構成が、使い勝手の決め手になると言っても過言ではないでしょう。
こちらも是非
“もっと見る” Cortex-M編
SysTick、電力管理
SysTick機能を有効にするには、SysTick制御およびステータスレジスタを使用します。このレジスタのENABLEビットを1にすると、カウンタは動作をはじめます。つまり、カウンタにリロード値がロードされてから、カウントダウンが開始されます。
メモリマップ
Cortex-M3のメモリマップには、一般的なマイコンのメモリマップと若干異なる特徴があります。一般的なマイコンでは、メモリ領域を変更できるものもあります。しかし、Cortex-M3のメモリマップは定義されたメモリマップになっており、アドレス領域のマッピングは固定です。
ベクタテーブル
Cortex-M3のベクタテーブルは0番地から始まります。一般的なマイコンは、ベクタテーブルの最小アドレス部(0番地)にはリセットベクタが割り当てられていますが、Cortex-M3ではメインスタック(SP_main)の初期値が割り当てられています。