#pragma mc_func ディレクティブを使用すると、短いシーケンスのマシン・インストラクションを含む関数を定義することができます。
.-----------------. V | >>-#--pragma--mc_func--function--{----instruction_seq-+--}-----><
ここで、
function | C または C++ プログラムで前に定義されている関数を指定します。関数が以前に定義されていない場合、コンパイラーはこのプラグマを関数定義として扱います。 |
instruction_seq | ゼロ以上の 16 進数字のシーケンスを含むストリングです。 桁の数は 32 ビットの整数倍で構成されていなければなりません。 |
mc_func プラグマを使用すると、マシン・インストラクション「inline」の短いシーケンスをプログラムのソース・コードの中に埋め込むことができます。このプラグマは、 通常のリンケージ・コードではなく、決まった所に指定された命令を生成するようコンパイラーに命令します。このプラグマを使用すると、アセンブラーでコーディングされた外部関数の呼び出しに関連したパフォーマンス上のペナルティーが避けられます。このプラグマは機能面において、このコンパイラーや他のコンパイラーで検出される asm キーワードに似ています。
mc_func プラグマは関数を定義し、プログラム・ソースの中で関数が通常定義される場所だけに現れます。 #pragma mc_func によって定義される関数名は、事前に宣言されているかプロトタイプ化されている必要があります。
コンパイラーは他の関数と同じ方法でこの関数にパラメーターを渡します。例えば、整数型の引数を取る関数では、1 番目のパラメーターが GPR3 に、2 番目が GPR4 に、と順番に渡されます。この関数によって戻される値は、整数値の場合は GPR3 で、浮動小数点または倍精度の値の場合は FPR1 になります。ご使用システムで使用可能な揮発性レジスターのリストについては、#pragma reg_killed_byを参照してください。
instruction_seq から生成されたコードは、#pragma reg_killed_by を使用して、関数によって使用される特定のレジスター・セットをリストしない限り、ご使用システムで使用可能なすべての揮発性レジスターを使用することができます。
インライン化オプションは、#pragma mc_func で定義された関数には影響しません。ただし、#pragma isolated_call を使用すると、そのような関数のランタイム・パフォーマンスを改善することができます。
65535 バイトを超えるストリング・リテラルがプラグマ・マップに指定されると、通知メッセージが出され、プラグマは無視されます。
以下の例では、#pragma mc_func は add_logical と呼ばれる関数を定義するために使用されています。この関数は、 循環桁上げ で 2 つの int を加算するためのマシン・インストラクションで構成されています。つまり加算の結果桁上げが発生すると、その桁上げを合計に加算します。これはチェックサムの計算で頻繁に使用されます。
またこの例は、#pragma reg_killed_by を使用して、#pragma mc_func によって定義された関数によって変更できる特定の揮発性レジスターのセットをリストする方法も示しています。
int add_logical(int, int); #pragma mc_func add_logical {"7c632014" "7c630194"} /* addc r3 <- r3, r4 */ /* addze r3 <- r3, carry bit */ #pragma reg_killed_by add_logical gr3, xer /* only gpr3 and the xer are altered by this function */ main() { int i,j,k; i = 4; k = -4; j = add_logical(i,k); printf("¥n¥nresult = %d¥n¥n",j); }
関連情報