4.2.4.14 制御レジスタへの書き込みの検出,同期化処理挿入 【Professional 版のみ】 【V1.06.00 以降】

RH850のストア命令によって複数の制御レジスタを連続して更新するとき,制御レジスタの更新順序がソース・ファイルの記述順と一致しない場合があります。更新する順序を制御したい場合は,同期化処理を挿入する必要があります。

CC-RHでは,連続する制御レジスタへの書き込みを検出して,書き込み処理の情報を表示させることや,固定の同期化処理を挿入することができます。

制御レジスタのアドレス範囲とグループの情報を,#pragma register_groupで指定します。

#pragma register_groupは次の形式で指定します。

#pragma register_group 開始アドレス, 終端アドレス[, id="グループID"]

-

開始アドレス,終端アドレスは符号なし整数で指定します。8進,10進,16進整数を使用できます。

終端アドレスは,その番地がグループに所属するものとして扱います。

0x100番地から始まる16バイトの領域は次のように指定します。

#pragma register_group 0x100, 0x10f

-

グループIDは,制御レジスタが所属するグループを指定するための識別子です。

グループIDに使用できる文字は,アルファベット(a-z,A-Z,大文字小文字を区別します),数字(0-9),アンダースコア(_)のみです。

グループIDの長さに制限はありません。

-

連続していない同一のグループを指定するために,複数の#pragma register_groupに同じグループIDを指定することができます。

-

グループIDは省略することができます。省略した場合,その領域への書き込みは他のどの書き込みとも連続しないものとして扱います。

-

次の場合はエラーを出力します。

-

開始アドレスが終了アドレスより大きい場合

-

グループIDに使用できない文字を使用している場合

-

複数の#pragma register_groupで指定したアドレス範囲が重複している場合

 

#pragma register_group 0xfedf0000, 0xfedfffff, id="CPU"
#pragma register_group 0xfee00000, 0xfee0ffff, id="0"
 
#define REG1 (*(volatile unsigned char*)0xfedf0000)    /* CPUグループの制御レジスタ */
#define REG2 (*(volatile unsigned char*)0xfedf0001)    /* CPUグループの制御レジスタ */
#define REG_Z (*(volatile unsigned short*)0xfee00000)  /* 0グループの制御レジスタ */
 
void func(void) {
   REG1  = 0;
   REG2  = 1;
   REG_Z = 2;
}

(a)

上記の例を-store_reg=listオプションを指定してコンパイルすると,次のように判定し,書き込み処理があることのメッセージを標準エラー出力へ出力します。

-

REG1とREG2は同じグループなので,REG1への書き込みに対する同期化処理は不要である。

-

REG2とREG_Zは異なるグループなので,REG2への書き込みに対する同期化処理は必要である。

-

REG_Zへの書き込みの後,同じグループへの書き込みがあるかどうか不明なので,REG_Zへの書き込みに対する同期化処理は必要である。

src.c(10):M0536001:制御レジスタを更新します。(id=CPU, 0xfedf0001)
src.c(11):M0536001:制御レジスタを更新します。(id=0, 0xfee00000)

 

(b)

同じ例を-store_reg=list_allオプションを指定してコンパイルすると,同じグループへの連続する書き込みかどうかを判断せず,#pragma register_groupで指定したすべての制御レジスタへの書き込みに対してメッセージを出力します。

src.c(9):M0536001:制御レジスタを更新します。(id=CPU, 0xfedf0000)
src.c(10):M0536001:制御レジスタを更新します。(id=CPU, 0xfedf0001)
src.c(11):M0536001:制御レジスタを更新します。(id=0, 0xfee00000)

 

(c)

同じ例を-store_reg=syncオプションを指定してコンパイルすると,(a)と同じ判定を行い,メッセージを出力するかわりに,出力コード中に同期化処理を挿入します。同期化処理には,同じ制御レジスタからのロードと,syncp命令を組み合わせて出力します。

出力例

_func:
        .stack _func = 0
        movhi 0x0000FEDF, r0, r2
        st.b r0, 0x00000000[r2]
         ; 同じグループへの書き込みが後ろにあるので,同期化処理を挿入しない
        movhi 0x0000FEDF, r0, r2
        mov 0x00000001, r5
        st.b r5, 0x00000001[r2]
        ld.bu 0x00000001[r2], r10  ; 同期化処理を挿入する
        syncp                      ;
 
        movhi 0x0000FEE0, r0, r2
        mov 0x00000002, r5
        st.h r5, 0x00000000[r2]
        ld.hu 0x00000002[r2], r10  ; 同期化処理を挿入する
        syncp                      ;
        jmp [r31]

[注意事項]

-

-Xmerge_fileオプションと同時に#pragma registr_groupを使用する場合,ソース・ファイル間で矛盾する#pragma register_groupを指定してもエラーとならず,意図しない結果になる可能性があります。#pragma register_groupはインクルード・ファイルに記述して,各ソース・ファイル間で共有することを推奨します。

-

制御レジスタへの書き込みと同期化処理の間に例外が発生し,例外ハンドラ内で同期化が必要な場合は,手動で同期化処理を挿入する必要があります。