10.159 名前付きレジスタ変数

コンパイラを使用すると、名前付きレジスタ変数を使用して、ARM アーキテクチャベースのプロセッサまたはコプロセッサのレジスタにアクセスできます。

構文

register type var-name __asm( reg );
各項目には以下の意味があります。
タイプ
名前付きレジスタ変数の型を指定します。
レジスタに名前を付ける際、同サイズであればいずれの型でも、名前付きレジスタ変数の宣言に使用できます。型は構造体でも可能ですが、ビットフィールドのレイアウトはエンディアン方式の影響を受けます。
var-name
名前付きレジスタ変数の名前を指定します。
reg
ARM アーキテクチャベースのプロセッサ上のレジスタ名を示す文字列を指定します。コプロセッサレジスタの場合は、変数の使用方法に合わせて、コプロセッサを識別する文字列構文を指定します。
ARM アーキテクチャベースプロセッサの名前付きレジスタ変数とともに使用できるレジスタを次の表に示します。

表 10-19 ARM アーキテクチャベースのプロセッサで使用可能な名前付きレジスタ

レジスタ __asm の文字列 プロセッサ
APSR "apsr" すべてのプロセッサ
CPSR "cpsr" Cortex-M シリーズプロセッサを除くすべてのプロセッサ
BASEPRI "basepri" ARMv7-M プロセッサ
BASEPRI_MAX "basepri_max" ARMv7-M プロセッサ
CONTROL "control" ARMv6-M および ARMv7-M プロセッサ
DSP "dsp" ARMv6-M および ARMv7-M プロセッサ
EAPSR "eapsr" ARMv6-M および ARMv7-M プロセッサ
EPSR "epsr" ARMv6-M および ARMv7-M プロセッサ
FAULTMASK "faultmask" ARMv7-M プロセッサ
IAPSR "iapsr" ARMv6-M および ARMv7-M プロセッサ
IEPSR "iepsr" ARMv6-M および ARMv7-M プロセッサ
IPSR "ipsr" ARMv6-M および ARMv7-M プロセッサ
MSP "msp" ARMv6-M および ARMv7-M プロセッサ
PRIMASK "primask" ARMv6-M および ARMv7-M プロセッサ
PSP "psp" ARMv6-M および ARMv7-M プロセッサ
PSR "psr" ARMv6-M および ARMv7-M プロセッサ
r0r12 "r0""r12" すべてのプロセッサ
r13 または sp "r13" または "sp" すべてのプロセッサ
r14 または lr "r14" または "lr" すべてのプロセッサ
r15 または pc "r15" または "pc" すべてのプロセッサ
SPSR
"spsr"
Cortex-M シリーズプロセッサを除くすべてのプロセッサ
XPSR "xpsr" ARMv6-M および ARMv7-M プロセッサ
浮動小数点ハードウェアを持つターゲットでは、次の表に示されているレジスタは名前付きレジスタ変数とともに使用することもできます。

表 10-20 浮動小数点ハードウェアを持つターゲットで使用可能な名前付きレジスタ

レジスタ __asm の文字列
FPSID "fpsid"
FPSCR "fpscr"
FPEXC "fpexc"
FPINST "fpinst"
FPINST2 "fpinst2"
FPSR "fpsr"
MVFR0 "mvfr0"
MVFR1 "mvfr1"

レジスタの中には一部のアーキテクチャで利用できないものもあります。

使用法

コアレジスタは、ローカルではなく、グローバル名前付きレジスタ変数として宣言しなければなりません。それらをローカルに宣言しても、プログラムがコンパイルする可能性はありますが、そうした場合、実行時に予期しない動作が発生する可能性があります。その他のレジスタの場合、名前付きレジスタ変数の有効範囲に制約はありません。

グローバル名前付きレジスタ変数は、プログラムに対してグローバルなのではなく、宣言されたソースファイルに対してグローバルです。この変数は、マルチファイルのコンパイルを使用するか、ヘッダファイル内で宣言しない限り、他のファイルには影響しません。

制約条件

コアレジスタを名前付きレジスタ変数として宣言することは、コンパイラが他の演算のためにそのレジスタを使用できなくなることを意味します。多くの名前付きレジスタ変数を宣言すると、コードサイズは著しく増大します。場合によっては、例えば、特定の式を計算するために使用できるレジスタが十分にない場合に、プログラムがコンパイルできなくなってしまう可能性があります。
名前付きレジスタ変数を宣言することで、ARM アーキテクチャ向けプロシージャコール標準(AAPCS)で定義されているレジスタの使用方法が影響を受けることはありません。例えば、関数から結果値を返すために、r0 が必ず使用されます。これは、名前付きレジスタ変数として宣言されている場合でも当てはまります。
名前付きレジスタ変数は、コンパイラ専用機能です。r12 だけは例外ですが、リンカなどのツールでは、オブジェクトファイルでのレジスタの使用方法は変更されません。AAPCS では、r12 をインタープロシージャスクラッチレジスタとして予約しています。関数呼び出し間で値を保持する必要がある場合でも、r12 を名前付きレジスタ変数として宣言しないで下さい。

サンプル

以下のサンプルでは、apsr"apsr" レジスタの名前付きレジスタ変数として宣言されています。
register unsigned int apsr __asm("apsr");
apsr = ~(~apsr | 0x40);
この場合、以下の命令シーケンスが生成されます。
MRS r0,APSR ; formerly CPSR
BIC r0,r0,#0x40
MSR CPSR_c, r0
以下のサンプルでは、PMCR は、コプロセッサ cp15 に関連付けられたレジスタ変数として宣言されています。MCR または MRC 命令には、CRn = c9CRm = c12opcode1 = 0、および opcode2 = 0 が使用されます。
register unsigned int PMCR __asm("cp15:0:c9:c12:0");
__inline void __reset_cycle_counter(void)
{
    PMCR = 4;
}
逆アセンブルした出力結果を以下に示します。
__reset_cycle_counter PROC
    MOV    r0,#4
    MCR    p15,#0x0,r0,c9,c12,#0
    BX     lr
    ENDP
以下のサンプルでは、cp15_control は、コプロセッサレジスタにアクセスするためのレジスタ変数として宣言されています。この例では、CP15 を使用して MMU を有効にします。
register unsigned int cp15_control __asm("cp15:0:c1:c0:0");
cp15_control |= 0x1;
以下の命令シーケンスが生成されます。
MRC  p15,#0x0,r0,c1,c0,#0
ORR  r0,r0,#1
MCR  p15,#0x0,r0,c1,c0,#0
以下は Cortex-M3 のサンプルです。_msp_control、および _psp がスタックポインタを設定するための名前付きレジスタ変数として宣言されています。
register unsigned int _control __asm("control");
register unsigned int _msp     __asm("msp");
register unsigned int _psp     __asm("psp");void init(void)
{
  _msp = 0x30000000;        // set up Main Stack Pointer
  _control = _control | 3;  // switch to User Mode with Process Stack
  _psp = 0x40000000;        // set up Process Stack Pointer
}
この場合、以下の命令シーケンスが生成されます。
init
  MOV r0,#0x30000000
  MSR MSP,r0
  MRS r0,CONTROL
  ORR r0,r0,#3
  MSR CONTROL,r0
  MOV r0,#0x40000000
  MSR PSP,r0
  BX lr
関連する概念
4.14 名前付きレジスタ変数を使用したレジスタへのアクセスに対するコンパイラサポート
関連情報
『Procedure Call Standard for the ARM Architecture』
非機密扱いPDF file icon PDF 版ARM DUI0472LJ
Copyright © 2010-2015 ARM.All rights reserved.