4.2.4.1 データとプログラムのセクション割り当て

CC-RHでは,C言語レベルでモジュールやデータを任意のセクションに割り当てることができます。これにより,それぞれのセクション再配置属性の性質を利用した配置を指定することができます。

 

(1)

#pragma section指令

#pragma section指令で次のような書式で記述します。

#pragma section 属性指定文字 "セクション名"
変数/関数の宣言/定義
#pragma section 属性指定文字
変数/関数の宣言/定義
#pragma section [文字列]
変数/関数の宣言/定義

 

属性指定文字でセクション再配置属性を,“セクション名”でセクション名をそれぞれ指定します。本pragma以降に記述された静的変数はセクション再配置属性に沿って,指定されたセクションに配置されます。

 

“#pragma section 属性指定文字”の形式と“#pragma section [文字列]”の形式で,「属性指定文字」と「文字列」が同一の場合は,メッセージを出さずに“#pragma section 属性指定文字”の形式とみなします。ただし,-Xcheck=shcオプションを指定した場合は,“#pragma section 属性指定文字”の形式とみなした場合にメッセージが出力されます。

「属性指定文字」と「文字列」の同一性は,大小文字を含めて同一性を確認します。そのため,たとえば,大文字のR0_DISP32は属性指定文字とみなしません。

#pragma section r0_disp32       /*これはdataが属性指定文字と一致するので,*/
                                /*“#pragma section 属性指定文字”の形式とする*/
#pragma section R0_DISP32       /*これは属性指定文字と大小文字が異なるので,*/
                                /*“#pragma section [文字列]”の形式とする*/

 

セクション名が数値(0〜9)で始まる場合,セクション名先頭に“_”を付加します。

#pragma section 123 → セクション名:_123.bss,_123.const,_123.text,...

 

文字列に使用可能な文字は,次のとおりとする。

- 0〜9

- a〜z, A〜Z

- _

- @

- .

 

#pragma sectionの効果は変数と関数で異なります。

-

変数

#pragma section系は「宣言,定義のいずれか一方のみ#pragma sectionが指定されている」場合,#pragma section指定されている側が有効です。

#pragma section系は「宣言,定義で別の#pragma sectionが指定されている」場合,最初に現れた#pragma section指定が有効です。

-

関数

#pragma section系は常に関数定義に対してのみ有効です。

(a)

“#pragma section 属性指定文字 "セクション名" ”の指定方法

デフォルト・セクション名を変更し,#pragma 以降で宣言した変数を新しいセクション名で配置します。

-

本pragma指令は,デフォルト・セクション名をユーザ指定のセクション名に変更します。

-

本pragma 指令は,外部変数/文字列リテラル/関数内static変数/関数に対して有効です。

-

本pragma指令は,記述された時点で以前の同じ属性への指定は無効になり,新たなセクション指定が有効となります。新たなセクションを指定しない場合,ファイルの終わりまで有効です。

-

再配置属性にdefaultを指定した場合,それ以降#pragma section のないデフォルトの割り付けに戻ります。defaultはすべての#pragma section 記述が無効になります。

-

変数の初期化がない場合は,指定された再配置属性に対し対応するbss系のセクションに配置されます。

-

文字列リテラルは,デフォルトでは.constに割り付けられます。#pragma sectionに対しては他のconstオブジェクトと同様に配置先が決定されます。

-

セクション名には,ユーザ指定文字列に続けて,自動で再配置属性を示す文字列が付加されます。これは,初期化の有無により,自動で再配置属性を切り替えた場合,同名のセクションができてしまうのを避けるためです。
例)#pragma section r0_disp32 "xxx" → セクション名:xxx.data

表 4.16

セクション再配置属性

対象

名前変更可能な属性指定文字

デフォルト・セクション名

ユーザ変更セクション名

定義系

(data系)

r0_disp16

r0_disp23

r0_disp32

ep_disp4

ep_disp5

ep_disp7

ep_disp8

ep_disp16

ep_disp23

gp_disp16

gp_disp23

 

 

.zdata

.zdata23

.data

.tdata4

.tdata5

.tdata7

.tdata8

.edata

.edata23

.sdata

.sdata23

xxx.zdata

xxx.zdata23

xxx.data

xxx.tdata4

xxx.tdata5

xxx.tdata7

xxx.tdata8

xxx.edata

xxx.edata23

xxx.sdata

xxx.sdata23

宣言系

(bss系)

.zbss

.zbss23

.bss

.tbss4

.tbss5

.tbss7

.tbss8

.ebss

.ebss23

.sbss

.sbss23

xxx.zbss

xxx.zbss23

xxx.bss

xxx.tbss4

xxx.tbss5

xxx.tbss7

xxx.tbss8

xxx.ebss

xxx.ebss23

xxx.sbss

xxx.sbss23

const系

const

zconst

zconst23

.const

.zconst

.zconst23

xxx.const

xxx.zconst

xxx.zconst23

text系

text

.text

xxx.text

指定解除

default

すべての指定を解除して,デフォルトのセクション名に戻します。

セクション名を“xxx”と書いた場合の実セクション名です。

例 1.

#pragma section r0_disp32   "mydata"
int i = 0;                      /*“mydata.data”に割り当てられる*/
int j;                          /*“mydata.bss”に割り当てられる*/
 
#pragma section gp_disp16   "mydata2"
int i2 = 1;                     /*“mydata2.sdata”に割り当てられる*/
 
#pragma section const       "myconst"
const int c2 = 0;               /*“myconst.const”に割り当てられる*/
int j2;                         /*“.bss”に割り当てられる*/

例 2.

#pragma section ep_disp4    "XXX"
extern  int     i;
void func()
{
        i = 5;
}
#pragma section r0_disp32 "OOO"
int     i = 5;                  /*"XXX.tdata4"に割り当てられる*/
                                /*最初の宣言にかかる #pragma section がある場合,*/
                                /*それが有効*/

例 3.

#pragma section ep_disp4
int     i;
#pragma section ep_disp23
int     i;                      /*".tbss4"に割り当てられる*/
                                /*最初の宣言にかかる#pragma sectionがある場合,*/
                                /*それが有効*/

例 4.

<def.c>
#pragma section ep_disp4
extern  int     i;
#pragma section ep_disp4 "XXX"
int i = 5;                      /*".tdata4"に割り当てられる*/
                                /*最初の宣言にかかる#pragma sectionがある場合,*/
                                /*それが有効*/
 
<use.c>
#pragma section ep_disp4
extern  int     i;
void func()
{
        i = 5;                  /*アクセスに問題なし*/
}

例 5.

#pragma section ep_disp4    "XXX"
extern  int     i;
#pragma section ep_disp4    "OOO"
int     i = 5;                  /*".tdata4"に割り当てられる*/
                                /*最初の宣言にかかる#pragma sectionがある場合,*/
                                /*それが有効*/

例 6.

#pragma section r0_disp16   "myzdata"
#pragma section const       "myconst"   /*この行で"myzdata"の指定はなくなる*/
int     i = 0;                          /*.data constでないので効かない*/
const int       ci = 0;                 /*myconst.const*/
#pragma section r0_disp16   "myzadata"  /*再度指定*/
int     j = 0;                          /*myzdata.zdata になる*/
const int       cj = 0;                 /*.const 直前のpragmaでmyconst指定は*/
                                        /*打ち消され".const"に配置される*/

例 7.

extern  int     i;
 
#pragma section ep_disp4
int     i;      /*".tbss4"に配置する*/
                /*宣言側と相違あるが,仮に他翻訳単位で*/
                /*#pragma section ep_disp23なしでアクセスしたとしても,*/
                /*長距離(効率悪い)アドレッシング・モードでアクセスが正常動作する*/

例 8.

#pragma section ep_disp23
#pragma section default
extern  int     i;
 
#pragma section ep_disp4
int     i;      /*".tbss4"に配置する*/
                /*デフォルト・セクション名に戻す#pragma section defaultは,*/
                /*セクション指定とみなさない*/
                /*extern宣言側は,セクション指定がないものとみなす*/

(b)

“#pragma section 属性指定文字”の指定方法

#pragma以降で宣言した変数をデフォルト・セクション名で配置します。

-

デフォルトのセクション名で,データの配置位置を指定します。

-

デフォルトのセクション名に配置されることを除けば,配置規則は“#pragma section 属性指定文字 "セクション名" ”と同一です。

表 4.17

セクション再配置属性

対象

属性指定文字

デフォルト・セクション名

定義系

(data系)

r0_disp16

r0_disp23

r0_disp32

ep_auto

ep_disp4

ep_disp5

ep_disp7

ep_disp8

ep_disp16

ep_disp23

gp_disp16

gp_disp23

 

 

.zdata

.zdata23

.data

.tdata4/.tdata5/.tdata7/.tdata8から自動選択

.tdata4

.tdata5

.tdata7

.tdata8

.edata

.edata23

.sdata

.sdata23

宣言系

(bss系)

.zbss

.zbss23

.bss

.tbss4

.tbss5

.tbss7

.tbss8

.ebss

.ebss23

.sbss

.sbss23

const系

const

zconst

zconst23

.const

.zconst

.zconst23

text系

text

.text

指定解除

default

すべての指定を解除して,デフォルトのセクション名に戻します。

 

#pragma section gp_disp16
int a = 1;                      /*.sdataセクションに配置する*/
int b;                          /*.sbssセクションに配置する*/

 

-

ep_autoは宣言の型に応じて,ep_disp4/ep_disp5/ep_disp7/ep_disp8のいずれかとして動作します。

宣言の型

対応するep_dispn

unsigned char

ep_disp4

unsigned short

ep_disp5

signed char

char

_Bool

ep_disp7

signed short

signed int

unsigned int

signed long

unsigned long

signed long long

unsigned long long

float

double

long double

ポインタ

列挙型(int型サイズの場合)

ep_disp8

 

備考 1.

配列型は,要素の型に応じて対応するep_dispnを選択します。ただし,多次元配列(配列の配列)の場合は,多次元配列に格納する要素の型とします。

#pragma section ep_auto
char    c_ary[3][5] = {0};      //.tdada7 (char)
char*   p_ary[3][5] = {0};      //.tdata8 (ポインタ)

備考 2.

-Xenum_typeオプションの作用により列挙型がintよりも小さな型になる場合,小さくなった型に応じて対応するep_dispnを選択します。

備考 3.

構造体および共用体は,.tdata4/.tdata5/.tdata7/.tdata8のいずれにも配置しません。

 

-

ep_autoは宣言の型に応じて,ep_disp4/ep_disp5/ep_disp7/ep_disp8のいずれかとして動作するため,宣言と定義でep_autoとep_dispnが同一の意味になる場合はエラーになりません。異なる意味となる場合はコンパイル・エラーとなります。

例 1.

#pragma section ep_auto
extern  unsigned char   ch;
#pragma section ep_disp4
unsigned char           ch;     /*エラーも警告もなしで,.tbss4 に配置する*/

例 2.

#pragma section ep_auto
extern  unsigned char   ch;
#pragma section ep_disp7
unsigned char           ch;     /*エラーも警告もなしで,.tbss4 に配置する*/
                                /*最初の宣言にかかる#pragma sectionがある場合,*/
                                /*それが有効*/

(c)

“#pragma section [文字列]”の指定方法

コンパイラが出力するセクション名を切り替えます。

デフォルトのセクション名と切り替え後のセクション名は,次のとおりです。

対象

指定方法

デフォルト

切り替え後

プログラム

#pragma section xxx

text

xxx.text

定数

const

xxx.const

初期値ありデータ

data

xxx.data

初期値なしデータ

bss

xxx.bss

 

-

文字列を省略した場合,すべてのセクション名をデフォルトに設定します。

#pragma section abc
int a;                  /*aはセクションabc.bssに割り付きます*/
const int d=1;          /*dはセクションabc.constに割り付きます*/
void f(void)            /*fはセクションabc.textに割り付きます*/
{
        a = d;
}
 
#pragma section
int b;                  /*bはセクション.bssに割り付きます*/
void g(void)            /*gはセクション.textに割り付きます*/
{
        b = d;
}
 
#pragma section 123
int c;                  /*cはセクション_123.bssに割り付きます*/
void h(void)            /*hはセクション_123.textに割り付きます*/
{
        c = d;
}