コプロセッサ

コプロセッサの概要

コプロセッサとは?

ARMプロセッサ(Cortex-Mシリーズを除く)を使用する場合、プロセッサ機能のキャッシュやMMUなどの設定はコプロセッサで行うため、コプロセッサレジスタを理解しなければなりません。コプロセッサは、メモリ空間に配置されていないため、専用命令を使用し、読み込みおよび書き込みを行います。メモリ空間に配置されないことで、4Gバイトすべてのメモリ空間を有効に使用できるメリットがあります。特権モードでしかアクセスできないコプロセッサレジスタがありますので、ご利用のプロセッサの「テクニカルリファレンスマニュアル(*1)」を参照ください。

  • ●コプロセッサは、16個のコプロセッサが定義されています。
  • ●CP15(コプロセッサ15)は、システム制御機能を提供します。
  • ●CP11(コプロセッサ11)は、倍精度の浮動小数点演算をサポートします。
  • ●CP10(コプロセッサ10)は、単精度の浮動小数点演算に加えて、VFPアドバンスドSIMDの両方のアーキテクチャの機能拡張をサポートします。
図1

コプロセッサのアクセス命令

コプロセッサのアクセスは、MRC/MCR命令で行います。特権モードでしかアクセスできないコプロセッサレジスタがありますので、注意して使用します。

MRC命令

MRC命令は、コプロセッサレジスタからプロセッサレジスタに読み込みを行います。

								MRC{ cond } coproc,# opcode1,Rd,CRn,CRm {, # opcode2 }
								
設定項目 設定内容
cond 任意の条件コードを指定します。
coproc 命令が実行されるコプロセッサの名前を指定します。
コプロセッサcp15の場合は、p15設定となります。
opcode1 3ビットコプロセッサ固有のオペコードを指定します。
opcode2 オプションとしての3ビットコプロセッサ固有のオペコードを指定します。
Rd デスティネーションプロセッサレジスタを指定します。r15(PC)は設定できません。
CRn コプロセッサレジスタを指定します。
CRm コプロセッサレジスタを指定します。

MCR命令

MCR命令は、プロセッサレジスタからコプロセッサレジスタに書き込みを行います。

								MCR{ cond } coproc,#opcode1,Rd,CRn,CRm {, # opcode2 }
								
設定項目 設定内容
cond 任意の条件コードを指定します。
coproc 命令が実行されるコプロセッサの名前を指定します。
コプロセッサcp15の場合は、p15設定となります。
opcode1 3ビットコプロセッサ固有のオペコードを指定します。
opcode2 オプションとしての3ビットコプロセッサ固有のオペコードを指定します。
Rd ソースプロセッサレジスタを指定します。r15(PC)は設定できません。
CRn コプロセッサレジスタを指定します。
CRm コプロセッサレジスタを指定します。

コプロセッサへのアクセス方法

ARMコンパイラを使用して、コプロセッサにアクセスする場合、“__asm”キーワードを使用したインラインアセンブリ言語またはアセンブリ言語で作成します。

C/C++コンパイラでのコプロセッサにアクセスする例

インラインアセンブリ言語を使用する場合、アセンブリ命令を__asm{....}でまとめて記述できます。

								void enable_caches( void )
								{
								  unsigned long reg;

								__asm {
								  MRC  p15,0,reg,c1,c0,0       // SCTLR(システム制御レジスタ)を読み込み
								  ORR  reg,reg,#(0x1 << 12)    // 命令キャッシュを許可(SCTLR.I [12])
								  ORR  reg,reg,#(0x1 <<  2)    // データキャッシュを許可(SCTLR.D [2])
								  ORR  reg,reg,#(0x1 << 11)    // プログラムフロー予測を許可(SCTLR.Z [11])
								  MCR  p15,0,reg,c1,c0,0       // SCTLRを書き込み
								//==================================================================
								// Cortex-A9のデータプリフェッチ機能を許可
								//==================================================================
								  MRC  p15,0,reg,c1,c0,1       // ACTLR(補助制御レジスタ)を読み込み
								  ORR  reg,reg,#(0x1 << 2)     // データプリフェッチ起動を有効 (ACTLR.DP[2])
								  MCR  p15,0,reg,c1,c0,1       // ACTLRを書き込み
								  }
								}
								

アセンブリ言語のコプロセッサにアクセスする例

AAPCS(ARMアーキテクチャのプロシージャコール標準)」に従って、アセンブリプログラムを作成することで、C/C++言語から関数としてコプロセッサアクセス命令を実行することができます。

								EXPORT enable_caches        ; キャッシュ・分岐予測の許可

								enable_caches  FUNCTION
								  MRC  p15,0,r0,c1,c0,0     ; SCTLRを読み込み
								  ORR  r0,r0,#(0x1 << 12)   ; 命令キャッシュを許可(SCTLR.I[12])
								  ORR  r0,r0,#(0x1 <<  2)   ; データキャッシュを許可します。(SCTLR.D[2])
								  ORR  r0,r0,#(0x1 << 11)   ; プログラムフロー予測を許可します。(SCTLR.Z[11])
								  MCR  p15,0,r0,c1,c0,0     ; SCTLRを書き込み
								;==================================================================
								; データプリフェッチ機能を許可
								;==================================================================
								  MRC  p15,0,r0,c1,c0,1     ; ACTLRを読み込み
								  ORR  r0,r0,#(0x1 << 2)    ; データプリフェッチ起動を有効 (ACTLR.DP[2])
								  MCR  p15,0,r0,c1,c0,1     ; ACTLRを書き込み
								  BX   lr
								  ENDFUNC
								

コプロセッサ設定例

Cortex-A9プロセッサの初期化処理を行う場合、コプロセッサ15(CP15)に設定を行います。今回は、以下の設定に関して説明します。

  • ●TLB (変換ルックアサイドバッファ)と分岐予測のアレイを無効化
  • ●命令/データキャッシュの無効化
  • ●VFP/NEONのアクセス権と設定
  • ●ベクタアドレスの変更設定
  • ●キャッシュ・MMU・分岐予測の設定

TLBと分岐予測器のアレイの無効化

TLBと分岐予測器は、リセット時に初期化されませんので、初期化時に無効化します。

【サンプルプログラム】

								;==================================================================
								; TLBと分岐予測器アレイの無効化
								;==================================================================
								  MOV   r0,#0               ; 初期値を設定
								  MCR   p15,0,r0,c8,c7,0    ; TLB全体無効化
								  MCR   p15,0,r0,c7,c5,6    ; 分岐予測器アレイ無効化			
								

TLBIALL (全体の無効化レジスタ)

  • ●統一TLB全体を無効化し、独立した命令TLBとデータTLBが実装されている場合は、同時に無効化します。
  • ●引数レジスタ<Rd>の設定値は無視し、特権モードのみで実行できます。

【レジスタへのアクセス命令】

								MCR    p15,0,<Rd>,c8,c7,0   ; TLB全体無効化の書き込み
								

BPIALL (分岐予測器アレイの無効化レジスタ)

  • ●分岐予測器アレイ全体を無効化します。
  • ●引数レジスタ<Rd>の設定値は無視し、特権モードのみで実行できます。

【レジスタへのアクセス命令】

								MCR    p15,0,<Rd>,c7,c5,6   ; 分岐予測器アレイ全体無効化の書き込み
								

命令/データキャッシュの無効化

リセット時にキャッシュは無効化されませんので、L1データキャッシュとL1命令キャッシュの無効化が必要です。データキャッシュは、ラインとウェイ毎に無効化が必要になりますので、CCSIDR (キャッシュサイズ識別レジスタ) から、キャッシュの情報を取得し無効化します。

【サンプルプログラム】

								  MOV   r0,#0                 ; 初期値に設定
								  MCR   p15,0,r0,c7,c5,0      ; 命令キャッシュ全体の無効化
								;
								; データキャッシュの無効化を行います。
								;
								  MOV  r10,#0                 ; データキャッシュを選択
								  MCR  p15,2,r10,c0,c0,0      ; キャッシュサイズ選択レジスタ(CSSELR)で
								                              ; データキャッシュを選択
								  ISB                         ; 命令同期バリア命令で再フェッチ
								  MRC  p15,1,r1,c0,c0,0       ; CCSIDRを読み込み
								  AND  r2,r1,#7               ; キャッシュラインサイズを取得(b001=8ワード/ライン)
								  ADD  r2,r2,#4               ; DCISWレジスタのセット番号のシフト数を求める
								  LDR  r4,=0x3FF              ; 最大ウェイ数マスク設定値を設定
								  ANDS r4,r4,r1,LSR #3        ; r4レジスタにウェイ数を設定
								  CLZ  r5,r4                  ; DCISWレジスタのウェイ番号のシフト数を求める
								  LDR  r7,=0x7FFF             ; セット数マスク設定値を設定
								  ANDS r7,r7,r1,LSR #13       ; r7レジスタにセット数を設定
								                              ; 0x7F=12Kbyte/0xFF=32Kbyte/0x1FF=64Kbyte
								Loop2
								  MOV  r9,r4                  ; r9レジスタにウェイ数を設定
								Loop3
								  ORR  r11,r10,r9,LSL r5      ; ウェイ番号とキャッシュ番号を設定
								  ORR  r11,r11,r7,LSL r2      ; セット番号を設定
								  MCR  p15,0,r11,c7,c6,2      ; DCISWレジスタでセット/ウェイによる
								                              ; データキャッシュラインの無効化
								  SUBS r9,r9,#1               ; ウェイ番号を-1
								  BGE  Loop3                  ; ウェイ毎の初期化を実施
								  SUBS r7,r7,#1               ; セット番号を-1
								  BGE  Loop2                  ; セット毎の初期化を実施
								

ICIALLU(命令キャッシュ全体の無効化レジスタ)

  • ●すべての命令キャッシュを無効化および分岐先キャッシュをフラッシュします。
  • ●引数レジスタ<Rd>の設定値は無視し、特権モードのみで実行可能です。

【レジスタへのアクセス命令】

								MCR    p15,0,<Rd>,c7,c5,0   ; ICIALLUの書き込み
								

CSSELR (キャッシュサイズ選択レジスタ)

  • ●CCSIDRの選択に使用します。
  • ●特権モードのみで、読み込み/書き込みできます。

【レジスタへのアクセス命令】

								  MCR p15,2,<Rd>,c0,c0,0       ; CSSELR読み込み
								  MCR p15,2,<Rd>,c0,c0,0       ; CSSELR書き込み
								

【レジスタフォーマット】

図2
ビット 名称 機能
3:1 レベル キャッシュのレベルを示します。
0b000:レベル1キャッシュ~0b110:レベル7キャッシュ
Cortex-A9プロセッサ内のキャッシュレベルは1レベルとなりますので、0b000となります。
0 InD 命令/データビット。
0:データまたは統一キャッシュ
1:命令キャッシュ

CCSIDR(キャッシュサイズ識別レジスタ)

  • ●キャッシュのアーキテクチャに関する情報を提供します。
  • ●プロセッサからアクセス可能なキャッシュ毎に、CCSIDRが実装されています。
  • ●CSSELRで、CCSIDRを選択します。
  • ●特権モードのみで、読み込みすることが出来ます。

【レジスタへのアクセス命令】

								MRC   p15,1,<Rd>,c0,c0,0      ; CCSIDR読み込み
								

【レジスタフォーマット】

図3
ビット 名称 機能
31 WT ライトスルーのサポート状態を示します。
0=該当機能がサポートされていません。
1=該当機能がサポートされています。
30 WB ライトバックのサポート状態を示します。
0=該当機能がサポートされていません。
1=該当機能がサポートされています。
29 RA リードアロケートのサポート状態を示します。
0=該当機能がサポートされていません。
1=該当機能がサポートされています。
28 WA ライトアロケートのサポート状態を示します。
0=該当機能がサポートされていません。
1=該当機能がサポートされています。
27:13 NumSets 「キャッシュラインのセット数-1」を示します。
0の場合は、1セットとなります。
12:3 Associativity 「キャッシュのアソシエティビィ-1」を示します。
0の場合は、アソシエティビィは1となります。
2:0 LineSize (log2(キャッシュラインのワード数))-2を示します。
ライン長が4ワードの場合:log2(4)=2, LineSizeエントリ=0
ライン長が8ワードの場合:log2(8)=2, LineSizeエントリ=1
  • ●命令キャッシュ値を読み出した場合、[31:28]ビットは、0b0010となります。
  • ●データキャッシュ値を読み出した場合、[31:28]ビットは、0b0111となります。

セット/ウェイによるDCISW(データキャッシュの無効化レジスタ)

  • ●セット/ウェイの設定するデータキャッシュラインの無効化を行います。
  • ●特権モードのみで、書き込みすることができます。

【レジスタへのアクセス命令】

								MCR    p15,0,<Rd>,c7,c6,2   ; セット/ウェイによるデータキャッシュ無効化の書き込み
								

【Cortex-A9のレジスタフォーマット】

図4
名前 機能
レベル 操作対象のキャッシュレベル-1
セット 操作対象のセット番号
ウェイ 操作対象のウェイ番号

セット/ウェイによるDCCSW(データキャッシュのクリーニングレジスタ)

  • ●セット/ウェイによるデータキャッシュラインのクリーンを行います。
  • ●特権モードのみで、書き込みできます。

【レジスタへのアクセス命令】

								MCR p15,0,<Rd>,c10,c6,2 ; セット/ウェイによるデータキャッシュのクリーンの書き込み
								

【Cortex-A9のレジスタフォーマット】

図5
名前 機能
レベル 操作対象のキャッシュレベル-1
セット 操作対象のセット番号
ウェイ 操作対象のウェイ番号

VFP/NEONのアクセス権と稼働設定

リセット時に、VFP/NEONのアクセスは禁止・非稼働状態に初期化されますので、初期化処理の中でアクセス権を設定し、稼働状態に設定することが必要です。
サンプルプログラムでは、コプロセッサ10(CP10)とコプロセッサ11(CP11)を完全アクセス設定を行い、アドバンスドSIMD拡張機能とVFP拡張機能を稼働に設定します。

【サンプルプログラム】

								;=====================================================================
								; NEON/VFPのアクセス許可
								; CP10/CP11の完全アクセス設定
								;=====================================================================
								   MRC   p15,0,r0,c1,c0,2   ; CPACRを読み込み
								   ORR   r0,r0,#(0xF << 20) ; CP10/CP11完全アクセス設定
								   MCR   p15,0,r0,c1,c0,2   ; CPACRを書き込み
								   ISB                      ; 命令同期バリアで再フェッチ
								;=====================================================================
								; VFPをNEON動作開始
								;=====================================================================
								  MOV   r0,#0x40000000      ;
								  VMSR FPEXC,r0             ; 浮動小数点例外レジスタでENビットを書き込み
								

CPACR(コプロセッサアクセス制御レジスタ)

  • ●コプロセッサCP10とCP11へのアクセス許可設定とアドバンストSIMDの拡張機能とVFPレジスタのレジスタアクセス制限を設定します。
  • ●特権モードのみで、読み込み/書き込みできます。

【レジスタへのアクセス命令】

								MRC p15,0,<Rd>,c1,c0,2 ; CPACR読み込み
								MCR p15,0,<Rd>,c1,c0,2 ; CPACR書き込み
								

【レジスタフォーマット】

図5
ビット 名称 内容
31 ASEDIS アドバンストSIMD拡張機能の非稼働を設定します。
0=未定義命令になることはありません。
1=「ARMアーキテクチャリファレンスマニュアル」で、アドバンストSIMD 拡張機能の一部であるが、VFPv3命令ではないとされているすべての命令エンコードが未定義になります。
30 D32DIS VFPレジスタのD16~D31の使用を不可能にします。
0=未定義命令になることはありません。
1=レジスタのD16~D31のいずれかにアクセスする場合、「ARMアーキテクチャ リファレンスマニュアル」でVFPv3命令とされているすべての命令エンコードが未定義になります。
23:22 cp11 コプロセッサのアクセス許可を設定します。
0b00=アクセス拒否が発生します(アクセスを行うと未定義例外が発生します)。
0b01=特権アクセスのみ可能です(ユーザモードのアクセスで未定義例外が発生します)。
0b10=予約。
0b11=完全アクセス。
21:20 cp10 コプロセッサのアクセス許可を設定します。
0b00=アクセス拒否が発生します(アクセスを行うと未定義例外が発生します)。
0b01=特権アクセスのみ可能です(ユーザモードのアクセスで未定義例外が発生します)。
0b10=予約。
0b11=完全アクセス。

FPEXC(浮動小数点例外レジスタ)

  • ●FPEXCでは、アドバンスドSIMD拡張機能とVFP拡張機能のグローバルな稼働/非稼働を制御できます。

【レジスタへのアクセス命令】

								VMRS { cond } Rd, extsysreg   ; NEON/VFPレジスタからARMレジスタの読み込み
								VMSR { cond } extsysreg , Rd  ; ARMレジスタからNEON/VFPレジスタの書き込み
								

【レジスタフォーマット】

図6
ビット 名称 内容
31 EX 例外ビット。アドバンスドSIMDシステムとVPFシステムを記憶するため、どの程度の情報を保存する必要が有るかを示すステータスビットです。
0=D0~D15/D16~D31(実装されている場合)/FPSCR/FPEXC
1=すべてのコンテキストスイッチシステムで処理する必要のある、他の状態が存在します。
30 EN アドバンスドSIMD拡張機能とVFP拡張機能を稼働/非稼働設定します。
0=アドバンスドSIMD拡張機能とVFP拡張機能が非稼働になります。(リセット時の初期値)
1=アドバンスドSIMD拡張機能とVFP拡張機能が稼働になります。

ベクタアドレスの変更設定

VBAR(ベクタベースレジスタ)にアドレスを設定することで、例外ベクタアドレスを変更できます。
SCTLRのVビットが1の場合、VBARによる再マッピングはできません。

【サンプルプログラム】

								;===================================================================
								; VBARを使用して、ベクタアドレスを変更
								;===================================================================
								  LDR    r0,=Vectors                  ; ベクタ先頭アドレスを設定
								  MCR    p15,0,r0,c12,c0,0            ; VBARに書き込み
								

VBAR

  • ●セキュリティ拡張機能が実装され、上位例外ベクタが選択されていない場合は、ベクタベースアドレスレジスタ(VBAR)によって、モニタモードで処理されない例外の例外ベースドレスが提供されます。
  • ●上位例外ベクタは常にベースドレスが0xFFFF_0000で、ベクタベースアドレスレジスタの影響は受けません。
  • ●特権モードのみで、読み込み/書き込みできます。

【レジスタへのアクセス命令】

								MRC p15,0,<Rd>,c12,c0,0 ; VBAR読み込み
								MCR p15,0,<Rd>,c12,c0,0 ; VBAR書き込み
								

【レジスタフォーマット】

図7
ビット 名称 内容
31:4 ベクタベースアドレス 16バイト境界でベクタベースアドレスを設定します。

キャッシュ・MMU・分岐予測の稼働設定

SCTLRで、キャッシュとMMU(第12回参照)の稼働状態に設定を行います。MMUを稼働するためには、各種設定を行っていただくことが必要になります。

【サンプルプログラム】

								  MRC   p15,0,r0,c1,c0,0    ; SCTLRを読み込み
								  ORR   r0,r0,#(0x1 << 12)  ; 命令キッシュを稼働(SCTLR.I [12])
								  ORR   r0,r0,#(0x1 <<  2)  ; データキッシュを稼働(SCTLR.D [2])
								  ORR   r0,r0,#(0x1 << 11)  ; プログラムフロー予測を稼働(SCTLR.Z [11])
								  ORR   r0,r0,#(0x1 <<  0)  ; MMUを稼働(SCTLR.M [0])
								  MCR   p15,0,r0,c1,c0,0    ; SCTLRを書き込み
								;==================================================================
								; データプリフェッチ機能を許可します。
								;==================================================================
								  MRC   p15,0,r0,c1,c0,1    ; ACTLRを読み込み
								  ORR   r0,r0,#(0x1 << 2)   ; データプリフェッチを稼働(ACTLR.DP[2])
								  MCR   p15,0,r0,c1,c0,1    ; ACTLRを書き込み
								

SCTLR

  • キャッシュ・MMU等のプロセッサの各種設定を行います。
  • 特権モードのみで、読み込み/書き込みできます。

【レジスタへのアクセス命令】

								MRC p15,0,<Rd>,c1,c0,0 ; SCTLR読み込み。
								MCR p15,0,<Rd>,c1,c0,0 ; SCTLR書き込み。
								

【レジスタフォーマット】

図8
ビット 名称 アクセス 内容
30 TE バンク Thumb例外イネーブル。
29 AFE バンク アクセスフラグイネーブルビット。
28 TRE バンク MMU内のTEX再マップ機能を制御します。
27 NMFI 読み出し専用 マスク不能FIQのサポート。
25 EE バンク 例外発生時の意CPSR.Eビットの設定方法を決定します。
0=リトルエンディアンの設定を行います。
1=ビックエンディアンの設定を行います。
17 HA - RAZ/WI(読み込み値0または、書き込み無視します。)
15 RR セキュア変更用 キャッシュ、BTAC、マイクロTLBの置き換え方式を設定します。
0=ランダム置き換え(リセット時の初期値)。
1=ラウンドロビン置き換え(非セキュアでは、読み出し専用です)。
13 V バンク 例外ベクタのベースアドレスを選択します。
0=通常の例外ベクタ0x00000000番地。
1=上位例外ベクタ0xFFFF0000番地(リマップ禁止)。
12 I バンク 命令キャッシュの動作を設定します。
0=命令キャッシュは非稼働です(リセット時の初期値)。
1=命令キャッシュは稼働です。
11 Z バンク プログラムフロー予測を可能にします。
0=プログラムフロー予測が非稼働です(リセット時の初期値)。
1=プログラムフロー予測が稼働です。
10 SW バンク SWP/SWPB許可ビット
0=SWPおよびSWPBは未定義です(リセット時の初期値)。
1=SWPおよびSWPBは正常に動作します。
2 C バンク データキャッシュの動作設定を行います。
0=データキャッシュは非稼働です(リセット時の初期値)。
1=データキャッシュは稼働です。
1 A バンク 非整列データのアクセスアライメントフォールトの検出を行います。
0=アライメントフォールトチェック禁止(リセット時の初期値)。
1=ライメントフォールトチェック許可。
0 M バンク MMUを稼働します。
0=MMUが非稼働です(リセット時の初期値)。
1=MMUが稼働です。

ACTLR

  • 特権モードのみで、読み込み/書き込みできます。

【レジスタへのアクセス命令】

								MRC p15,0,<Rd>,c1,c0,1 ; ACTLR読み込み
								MCR p15,0,<Rd>,c1,c0,1 ; ACTLR書き込み
								

【レジスタフォーマット】

図9
ビット 名称 内容
9 パリティ パリティチェックのサポート(実装されている場合)
0=非稼働です(リセット時の初期値)。
1=稼働しています。
8 1ウェイでの割り当て 1キャッシュウェイの割り当てを可能にします。
0=禁止です(リセット時の初期値)。
7 EXCL 排他キャッシュビット
0=非稼働です(リセット時の初期値)。
1=稼働しています。
6 SMP Cortex-A9プロセッサがコヒーレンシの一部かどうか示します。
3 0のフルライン書き込み 0のフルライン書き込みモードを可能にします。
リセット時は、0です。
2 L1プリフェッチイネーブル データサイドのプリフェッチ設定
0=非稼働です(リセット時の初期値)。
1=稼働しています。
1 L2プリフェッチヒントイネーブル プリフェッチヒントイネーブル設定。
リセット時は、0です。
0 FW キャッシュおよびTLB保守のブロードキャスト。
0=非稼働です(リセット時の初期値)。
1=稼働しています。

今回は、初期化をする時に設定が必要なコプロセッサを中心に解説しました。普通にプログラミングしていると、アクセスすることは少ないと思いますが(笑)、例外が発生した時に問題解決に役立つレジスタもありますので、マニュアルを読んでおくことをお勧めします。