セクション種別と変更セクションを指定した場合、セクション種別がPであればその#pragma 宣言以降に記述された関数のセクション名を変更します。セクション種別がC、D、またはBの場合は、その#pragma 宣言以降に実体を定義した全てのセクション名を変更します。
変更セクション名のみを指定した場合、その#pragma 宣言以降にあるプログラム領域、定数領域、初期化データ領域、および未初期化データ領域のすべてのセクション名を変更します。この場合、各セクションの変更後のセクション名は、各デフォルトセクション名の後に<変更セクション名>の文字列を追加したセクション名となります。
セクション種別も変更セクション名も記述しなかった場合は、その#pragma 宣言以降にあるプログラム領域、定数領域、初期化データ領域、および未初期化データ領域の全てのセクション名をデフォルトセクション名に戻します。
各セクション種別のデフォルトセクション名は、sectionオプションの指定があればそれに従います。ない場合はセクション種別名をそのまま用います。
#pragma section B Ba int i; // Baセクションに配置 void func(void) { (省略) } #pragma section B Bb int j; // Bbセクションに配置 void sub(void) { (省略) } |
#pragma section abc int a; // Babcセクションに配置 const int c=1; // Cabcセクションに配置 void f(void)// Pabcセクションに配置 { a=c; } #pragma section int b;// Bセクションに配置 void g(void)// Pセクションに配置 { b=c; } |
#pragma sectionは関数定義の外で宣言しなければなりません。
次の項目のセクション名は変更できません。sectionオプションを使用してください。
(1) 文字列リテラルおよび集成体の動的初期化で用いる初期化子
1ファイルあたりの#pragma sectionで指定できるセクション数は最大2045個です。
静的クラスメンバ変数のセクションを指定する場合は、クラスのメンバ宣言と実体の定義の両方または実態の定義時のみに#pragma section の指定が必要になります。
si=<定数>を指定した場合、セクション名SI、サイズ<定数>のスタックとして使用するデータセクションを作成します。
su=<定数>を指定した場合、セクション名SU、サイズ<定数>のスタックとして使用するデータセクションを作成します。
si, su指定はファイル内でそれぞれ1回しか指定できません。
<定数>に記述できる値の範囲は、4から2147483644(0x7ffffffc)までです。
#pragma interruptを用いて割り込み関数となる関数を宣言します。
関数名には、グローバル関数および静的関数メンバを指定できます。
#pragma interruptを用いて宣言した関数は、関数の処理の前後で全レジスタを保証(関数入口/出口において関数内で使用する全レジスタを退避・回復)し、通常RTE命令でリターンします。
割り込み仕様を指定しない場合は単純な割り込み関数として処理します。
ベクタテーブル指定(vect=)をした場合はC$VECTセクション内の指定したベクタテーブル番号位置にその関数アドレスを設定します。
高速割り込み指定(fint)をした場合は、RTFI命令でリターンします。また、fint_registerオプションを指定した場合は、オプションで指定したレジスタを退避、回復せずに割り込み関数で使用します。
割り込み関数レジスタ制限指定(save)をした場合は、割り込み関数内で使用するレジスタの本数をR1〜R5、およびR14〜R15に制限します。R6〜R13は割り込みで使用しないため、退避・回復命令は生成しません。
多重割り込み許可指定(enable)をした場合は、割り込み関数の先頭でPSWのIフラグを1にし、多重割り込みを許可します。
アキュムレータ保存指定(acc)をした場合で、指定された関数から別の関数呼び出しがあったり、関数内でアキュムレータを書き換える命令を使う場合は、アキュムレータを退避および回復する命令を生成します。なお、ISA(*1)にRXv1を選択するか、CPUでマイコン種別を選択(*2)した場合は、ACCを退避および回復する命令を生成します。ISA(*1)にRXv2を選択した場合は、ACC0と ACC1を退避および回復する命令を生成します。
アキュムレータ非保存指定(no_acc)をした場合は、ACC, ACC0, ACC1のいずれもを退避および回復する命令を生成しません。
acc およびno_accのどちらの指定もない場合は、コンパイルオプションに従います。
割り込み関数の定義に対して指定できる関数は、グローバル関数(C/C++言語)と静的関数メンバ(C++言語)です。
関数の返却値の型はvoid のみです。return 文の返却値を指定することはできません。指定があった場合はエラーを出力します。
関数内で使用しているレジスタに加えて、関数呼び出し前後で保証しないレジスタについても、割り込み関数の入口で退避し、出口で回復します。
Cソース: fint_register=2オプションを指定してコンパイル
void func5(void); #pragma interrupt accsaved_ih(acc) /* "acc"を指定 */ void accsaved_ih(void) { func5(); } |
_accsaved_ih: PUSHM R14-R15 PUSHM R1-R5 MVFACMI R4 SHLL #10H, R4 MVFACHI R5 PUSHM R4-R5 BSR _func5 POPM R4-R5 MVTACLO R4 MVTACHI R5 POPM R1-R5 POPM R14-R15 RTE |
- RX命令セットの仕様のため、accフラグで退避・回復できるのは、ACCの上位48ビットに限られます。
ACCの下位16ビットは退避・回復されません。
- 各割り込み仕様は、小文字のみ指定できます。大文字を指定してもエラーになります。
- 割り込み仕様としてvectを使った場合、指定の無い空きベクタのアドレスは0になります。このアドレスは、最適化リンケージエディタで任意のアドレスやシンボルに変更することができます。詳しくは、VECTおよびVECTNオプションの項目を参照してください。
- #pragma interruptの関数には、引数(仮引数)を定義することはできません。定義してもエラーにはなりませんが、引数から値を読み出しても、不定値が返されます。
- saveフラグとfintフラグを同時に有効にした場合は、R1〜R5、およびR14〜R15のほか、fint_registerオプションで確保したレジスタもコード生成に使用します。
・アキュムレータの補償をsave_accで行う場合の割り込み応答速度低下の対策(no_acc)
既存の割り込み関数でアキュムレータの補償にはsave_accオプションが有効だが、割り込み応答速度が悪化することがあるため、不要なACCの退避・回復を関数単位で抑止する手段をとしてno_accを用意する。
・アキュムレータの退避・回復をソースコードで制御(accとno_acc)
アキュムレータの退避・回復の考慮が完了している割り込み関数には、明示的にacc、no_accを選択しておくことで、ソースプログラムでアキュムレータの退避・回復をsave_accに依存せずに定義できる。
#pragma inline は、インライン展開する関数を宣言します。
noinlineオプションが指定された場合でも、#pragma inline指定された関数はインライン展開の対象となります。
#pragma noinline は、inlineオプションの指定を抑止する関数を宣言します。
関数名には、グローバル関数および静的関数メンバを指定できます。
#pragma inline で指定した関数名の関数と関数指定子inline(C++言語およびC(C99)言語)を指定した関数は、その関数を呼び出したところにインライン展開されます。
#pragma inline(func) static int func (int a, int b) { return (a+b)/2; } int x; main() { x=func(10,20); } |
#pragma inlineが指定された場合でも、以下のいずれかに該当する場合はインライン展開しません。
#pragma inlineは、インライン展開されることを保証するものではありません。コンパイル時間やメモリ使用量の増大を考慮した制限により、インライン展開を抑止することがあります。なお、インライン展開が抑止される際に、noscopeオプションを指定すると、インライン展開されるようになる場合があります。
#pragma inlineは、関数本体の定義の前に指定してください。
#pragma inline で指定した関数に対して外部定義を生成します。static関数に#pragma inlineを指定した場合、関数定義はインライン展開後に削除されます。
C++言語のコンパイルでは、inlineが指定された関数には、外部定義を生成しません。
C(C99)言語のコンパイルでは、inline指定された関数には、その関数にextern宣言がなければ、外部定義を生成しません。
#pragma inline_asmで宣言したアセンブリ記述関数をインライン展開します。
アセンブラ埋め込みインライン関数の呼び出し規則は通常関数の呼び出し規則と同様です。
#pragma inline_asm func static int func(int a, int b){ ADD R2,R1; アセンブリ記述 } main(int *p){ *p = func(10,20); } |
_main: PUSH.L R6 MOV.L R1, R6 MOV.L #20, R2 MOV.L #10, R1 ADD R2,R1; アセンブリ記述 MOV.L R1, [R6] MOV.L #0, R1 RTSD #04H, R6-R6 |
#pragma inline_asmは、関数本体の定義の前に指定してください。
#pragma inline_asmで指定したstaticではない関数に対して外部定義を生成します。
アセンブラ埋め込みインライン関数内で関数の出入口で保証するレジスタ(表 9.1 レジスタ使用規則を参照)を使用する場合は、アセンブラ埋め込みインライン関数の先頭と最後でこれらのレジスタの退避・回復が必要です。
- アセンブラ埋め込みインライン関数には、RXファミリの命令およびテンポラリラベルだけを記述してください。テンポラリラベル以外のラベルを定義したり、アセンブラ制御命令を記述することはできません。
-アセンブラ埋め込みインライン関数の最後にRTS を記述しないでください。
- static関数に#pragma inline_asmを指定した場合、関数定義はインライン展開後に削除されます。
- アセンブリ記述は、プリプロセッサの処理対象となります。このため、アセンブリ言語で使用される命令やレジスタと同じ名前のマクロ(例: "MOV"や"R5"など)を#defineでマクロ定義する場合はご注意ください。
-スタック情報ファイルは、#pragma inline_asmのアセンブリ記述内ではスタックが消費されないものとして扱います。アセンブリ記述内にR0を操作するコードを含める場合はご注意ください。
エントリ関数では、レジスタの退避・回復コードを一切作成しません。
#pragma stacksize 宣言があると、関数先頭でスタックポインタの初期設定コードを出力します。
baseオプションを指定した場合、オプションで指定したベースレジスタへの設定を行います。
.SECTION SU,DATA,ALIGN=4 .BLKB 100 .SECTION P,CODE _INIT: MVTC (TOPOF SU + SIZEOF SU),USP MOV.L #__ROM_TOP,R13 |
#pragma entry指定は、関数の宣言前に行ってください。
ロードモジュール全体でエントリ関数を複数指定することはできません。
leftを指定した場合は上位ビット側から、rightを指定した場合は下位ビット側から、それぞれメンバが割り付けられます。
left|rightを省略すると、以降はオプションに従います。
ソースプログラム中の指定位置以降の構造体メンバおよびクラスメンバのアライメント数を指定します。本拡張子が指定されていない場合または#pragma packoption 指定位置以降で宣言された構造体メンバおよびクラスメンバのアライメント数はpackオプションの指定に従います。#pragma pack拡張子とアライメント数の関係を表4.23に示します。
構造体、共用体、クラスメンバのアライメント数はpackオプションでも指定できます。オプションと#pragmaの両方が指定された場合は、#pragmaの指定を優先します。
指定した変数を指定したアドレスに割り付けます。その際、コンパイラが指定した変数ごとにセクションを設定し、リンク時に指定した絶対アドレスに割り付けます。連続したアドレスに変数を指定した場合、それらの変数は同一セクションにします。
_main: MOV.L #0,R5 MOV.L #7F00H,R14 ; MOV.L R5,[R14] RTS .SECTION $ADDR_B_7F00,DATA .ORG 7F00H .glb _X _X: ; static: X .blkl 1 |
- #pragma address指定は、変数の宣言前に行ってください。
- 構造体/共用体のメンバ、もしくは変数以外を指定した場合はエラーとなります。
- #pragma addressを同一の変数に対して複数回指定した場合はエラーとなります。
- #pragma address が有効でも、ソースファイル内で参照のないstatic変数は、最適化により削除される場合があります。
- 初期値を持ち、かつconst修飾のない変数に対して#pragma addressを適用することは推奨されません。もし該当する変数がある場合は、次の制限事項に注意してください。
・この変数に対応するセクションに、最適化リンカ(rlink)の-romオプション(ROM領域のRAM化)を
適用することはできません。
・この変数に書き込みを行ってもエラーや警告などのメッセージは表示されません。
・この変数に対応するセクションはRAMに配置し、スタートアップの実行またはその前に、すべての
初期値を該当するRAM領域に書き込んでおく必要があります。
#pragma endianを記述した行から、ファイルの末尾か、または次の#pragma endianを記述した行の手前までに定義したものが対象となります。
bigを指定した場合はbig endianになります。オプション指定がendian=littleである場合は、セクション名の後に_Bをつけたセクションに配置されます。
littleを指定した場合はlittle endianになります。オプション指定がendian=bigである場合は、セクション名の後に_Lをつけたセクションに配置されます。
big | little を省略すると、以降はオプションに従います。
.glb _A .glb _B .SECTION D,ROMDATA,ALIGN=4 _B: .lword 200 .SECTION D_B,ROMDATA,ALIGN=4 .ENDIAN BIG _A: .lword 100 |
endianオプションと異なる#pragma endian対象のオブジェクトに、long long型、double型(dbl_size=8オプション指定時)およびlong double型(同)の領域を含む場合は、これらの領域に対するアドレスやポインタを用いた間接的なアクセスはしないでください。この場合の動作は保証しません。
次の項目のエンディアンは変更できません。endianオプションを使用してください。
(1) 文字列リテラルおよび集成体の動的初期化で用いる初期化子
(3) 外部参照宣言されたオブジェクト(初期化式なくextern宣言されたオブジェクト)
(4) #pragma address により指定されたオブジェクト
#pragma instalign4 [(]<関数名>[(<分岐先の種類>)][,…][)] #pragma instalign8 [(]<関数名>[(<分岐先の種類>)][,…][)] #pragma noinstalign [(]<関数名>[,…][)] |
指定された関数に対し、#pragma instalign4の場合は4バイト、#pragma instalign8の場合は8バイトでそれぞれ配置アドレスを命令実行向け整合します。
#pragma noinstalignが指定された関数は、整合は行いません。
指定なし:関数先頭、switch文のcaseおよびdefaultラベル
inmostloop:各最内周ループの先頭、関数先頭、switch文のcaseおよびdefaultラベル
loop:各ループの先頭、関数先頭、switch文のcaseおよびdefaultラベル
ここに挙げたもの以外の分岐先は、命令実行向け整合の対象ではありません。たとえば、loopを選択した場合はループの先頭は対象ですが、ループ内にあるループを構成しないif文などの分岐先は対象ではありません。 |
それぞれ、指定した関数ごとに有効になることを除き、instalign4, instalign8, noinstalignオプションと機能は同じです。これらのオプションと同時に指定した場合は、#pragmaの指定が優先されます。instalign4またはinstalign8を選択した関数が属するコードセクションは、そのアライメント数は4(instalign4の場合)または8(instalign8の場合)に変わります。同じコードセクション内に、instalign4とinstalign8が指定された関数が混在する場合、そのコードセクションのアライメント数は8になります。
その他の内容については、instalign4, instalign8, noinstalignオプションと同様ですので、これらのオプションの項目を参照ください。
関数の入口・出口にスタック破壊検出コードを生成します。スタック破壊検出コードとは次に示す3つの処理を実行するための命令列を指します。
(1) 関数の入口で、ローカル変数領域の直前(0xFFFFFFFF番地に向かう方向)に4バイトの領域を確保し、その領域に<数値>で指定した値を格納します。
(2) 関数の出口で、<数値>を格納した4バイトの領域が書き換わっていないことをチェックします。
(3) (2)で書き換わっている場合には、スタックが破壊されたとして __stack_chk_fail 関数を呼び出します。
<数値>には 0 から 4294967295までの10進数または16進数の整数値を指定します。<数値>の指定を省略した場合には、コンパイラが自動的に数値を指定します。
__stack_chk_fail関数はユーザが定義する必要があり、スタックの破壊検出時に実行する処理を記述します。
__stack_chk_fail関数を定義する際には、次の項目に注意してください。
__stack_chk_fail関数は、-stack_protectorオプション、-stack_protector_allオプション、#pragma stack_protectorに関わらず、スタック破壊検出コードを生成しません。 |
#pragma no_stack_protector が指定された関数は-stack_protector オプション、-stack_protector_all オプションに関わらず、スタック破壊検出コードを生成しません。
#pragma stack_protector と-stack_protector オプション、-stack_protector_all オプションが同時に使用された場合は、#pragma 指定が有効になります。
同一翻訳単位内で、同じ関数に対して #pragma stack_protector と no_stack_protector を同時に指定する場合はエラーとします。
#pragma stack_protectorで指定した関数が次のいずれかの関数として指定されている場合、エラーメッセージを出力します。