日本-日本語
日本HPホーム 製品 & サービス OpenVMS製品情報
≫  お問い合わせ


OpenVMS マニュアル


 

OpenVMS ドキュメント
ライブラリ

タイトルページ
目次
まえがき
第 1 部 : 概念と方法
第 1 章:Macro-32コードの移植の準備
第 2 章:MACROコンパイラのプラットフォームごとの動作
第 3 章:ソースに対する推奨される変更と必要な変更
第 4 章:移植したコードの性能改善
第 5 章:MACROの64ビット・アドレッシングのサポート
第 2 部:リファレンス・セクション
付録 A :MACROコンパイラの修飾子
付録 B :専用の指示文
付録 C :MACROコンパイラ・ビルトイン
付録 D :VAXからAlphaまたはI64への移植用のマクロ
付録 E :64ビット・アドレッシング用のマクロ
索引
PDF
OpenVMS ホーム
HP OpenVMS MACRO コンパイラポーティングおよびユーザーズ・ガイド

HP OpenVMS MACRO コンパイラ
ポーティングおよびユーザーズ・ガイド


目次 索引



STARLET.MLB 内のマクロは,ルーチンにエントリ・ポイントを指定するための指示文を生成します。これら各マクロの形式についての詳細は, 付録 B を参照してください。

OpenVMS VAX システム用にアセンブルした場合, .CALL_ENTRY 以外のマクロはヌルです。 OpenVMS Alpha システムまたは OpenVMS I64 システム用にコンパイルした場合,マクロは,引数を確認しコンパイラ指示文を生成するために展開されます。そのため,以下のマクロを共通のソース・モジュールで使用できます。

  • .CALL_ENTRY 指示文は, Macro-32 コード中の .ENTRY 指示文を論理的に置き換えます。 ただし,いずれかの .CALL_ENTRY 句を使用する場合以外は, .ENTRY 指示文を置き換える必要はありません。 .ENTRY 指示文を置き換える場合は,引数が一致しないため,エディタで一括置換できない点に注意してください。

      注意
    .ENTRY 指示文は OpenVMS Alpha や OpenVMS I64 の .CALL_ENTRY 指示文に変換されるため, .ENTRY で宣言されたルーチンで変更されるレジスタは自動的に保護されます。これは,VAX MACRO の動作と異なります。 第 2.4.2 項 を参照してください。

  • .JSB_ENTRY 指示文は,JSB,BSBB, BSBW のいずれかの命令で呼び出されるルーチンを示します。 .JSB32_ENTRY 指示文は, Alpha または Itanium のレジスタ値の上位 32 ビットの保護が不要な特別な環境で使用されます。
    .JSB_ENTRY 指示文は,他のモジュールからのJMP 命令または分岐命令のターゲットとなるエントリ・ポイントを宣言するためにも使用する必要があります。これは,このようなモジュールにまたがった分岐は,コンパイラによって JSB として実装されるためです。
    JMP (R0) のように保存されたコード・アドレスへの分岐も JSB 命令として扱われます。そのため,ターゲットとなる可能性のあるエントリ・ポイントを .JSB_ENTRY で宣言する必要があります。コード・ラベルを保存しようとした場合や,このような分岐を使用した場合に,コンパイラはこれに関する警告を表示します。

  • .EXCEPTION_ENTRY 指示文 ( OpenVMS Alpha のみ) は,例外サービス・ルーチンを指定します。

  • .CALL_LINKAGE 指示文 ( OpenVMS I64 のみ) は,名前付きリンケージまたは匿名リンケージをルーチン名に関連付けます。コンパイラが,ルーチン名をターゲットとする CALLS,CALLG,JSB,BSBB, BSBW のいずれかの命令を見つけると,関連付けられているリンケージを使用して,呼び出しの前後で保存と復元が必要なレジスタを決定します。

  • .USE_LINKAGE 指示文 ( OpenVMS I64 のみ) は,一時的な名前付きリンケージまたは匿名リンケージを確立します。これは,コンパイラによって,字句解析の順で次に処理される CALLS, CALLG,JSB,BSBB,BSBW 命令に対して使用されます。

  • .DEFINE_LINKAGE 指示文 ( OpenVMS I64 のみ) は,以降の .CALL_LINKAGE 指示文または .USE_LINKAG 指示文で使用される名前付きリンケージを定義します。

これらの指示文についての詳細は, 付録 B を参照してください。

2.3.5 ルーチン呼び出しのコード生成

VAX の JSB,BSBW,BSBB 命令のコード生成は,パラメータ操作が不要のため非常に単純です。しかし,CALLS 命令と CALLG 命令のコード生成では, OpenVMS VAX の呼び出し規則のパラメータ処理を, OpenVMS Alpha または OpenVMS I64 の呼び出し規則に変換する必要があるため,より複雑です。

引数の個数が固定の CALLS 命令を処理する際には,コンパイラはルーチンにパラメータを渡すためのスタックへのプッシュを自動的に検出し, OpenVMS Alpha の呼び出し規則または OpenVMS I64 の呼び出し規則で使用されているレジスタに,パラメータを直接移動するコードを生成します。

VAX で次の呼び出しがあるとします。

PUSHL   R2 
PUSHL   #1 
CALLS   #2,XYZ 

VAX でのこの呼び出しは, OpenVMS Alpha では次のようにコンパイルされます。

SEXTL   R2, R17                  ; R2 is the second parameter 
LDA     R16, 1(R31)              ; #1 is the first parameter 
LDA     R25, 2(R31)              ; 2 parameters 
LDQ     R26, 32(R13)             ; Get routine address 
LDQ     R27, 40(R13)             ; Get routine linkage pointer 
JSR     R26, R26                 ; Call the routine 

VAX でのこの呼び出しは, OpenVMS I64 では基本的に次のようにコンパイルされます。

sxt4    r46 = r28                  ; Load 2nd output register 
adds    r45 = 1, r0                ; Load 1st output register 
adds    r25 = 2, r0                ; 2 parameters 
adds    r12 = -16, r12             ; Extra octaword per calling standard 
br.call.sptk.many br0 = XYZ ;;     ; Call the routine 
adds    r12 = 16, R16              ; Pop extra octaword 
mov     r1 = r32                   ; Restore saved GP 

生成されるコードは, OpenVMS Alpha と OpenVMS I64 の呼び出し規則の違いに合わせるために,正確には異なる可能性があります。

引数の数が可変の CALLS 命令または CALLG 命令の場合,コンパイラは,引数リストを OpenVMS Alpha 形式または OpenVMS I64 形式にアンパックするエミュレーション・ルーチンを呼び出す必要があります。これには 2 つの副作用があります。 OpenVMS VAX システムでは, CALLG 命令が指す引数リストの一部がアクセス不能でも,呼び出されたルーチンが引数リストのその部分にアクセスしなければ,ルーチンはアクセス違反にならずに正常に完了します。 OpenVMS Alpha システムと OpenVMS I64 システムでは,ルーチンを呼び出す前に引数リスト全体が処理されるため,引数リストのいずれかの部分がアクセス不能の場合, CALLG は常にアクセス違反となります。また,引数の個数が可変な CALLG 命令または CALLS 命令の引数の個数が 255 を超えている場合,エミュレートされた呼び出しがエラー状態を返し,ターゲット・ルーチンは呼び出されません。

2.4 CALL エントリ・ポイントの宣言

OpenVMS VAX , OpenVMS Alpha , OpenVMS I64 の呼び出し規則が違うため ( 第 2.3 節 を参照),コンパイラは AP 相対の VAX パラメータ参照をすべて,以下のように変換する必要があります。

  • 呼び出されるルーチン内の AP 相対のパラメータ参照を, OpenVMS Alpha または OpenVMS I64 の新しいパラメータ位置に対する,レジスタおよびスタックの直接参照に変換します。

  • AP 相対の参照のうち,パラメータ・リストへの別名参照となるものや,コンパイル時に解決できない変数オフセットを使用しているものを検出します。コンパイラは,クォドワード・レジスタとスタック引数をスタック上のロングワード引数リストにパックすることで, VAX の引数リストをまねます。 .CALL_ENTRY 指示文に対する 2 つの引数は,このために用意されています ( 第 2.4.1 項 を参照)。

後者の場合,この方法は引数リストのホーミングと呼ばれます。その結果得られるホーミングされた引数リストは,スタック・フレーム中の固定位置にあるため,すべての参照は FP ベースとなります。

2.4.1 ホーミングされた引数リスト

コンパイラが引数を自動的にホーミングする AP 参照の例としては,以下のものがあります。

  • AP または AP ベースのアドレスの別レジスタへの保存

  • AP または AP ベースのアドレスのパラメータとしての引き渡し

  • パラメータを参照するための AP への可変オフセットの加算

  • パラメータを参照するための AP 相対の可変インデックスの使用

  • 6(AP) のように,引数リスト中でのロングワードにアラインされていないオフセットの使用

コンパイラは,スタック上のプロシージャ・フレームの固定的な一時領域に,ホーミングされた引数リストを設定します。

必須ではありませんが,.CALL_ENTRY 指示文に対する 2 つの引数 home_args=TRUE および n を使用して,ホーミングを指定することができます。

引数 n は,コンパイラが固定的な一時領域に割り当てるロングワードの最大数を表します。 n を使用する主な理由は,ソース・コード中で明示的に使用されている数よりも多くの引数をプログラムが受け取った場合に備えることです。 home_args=TRUE を必要としないルーチンにこのパラメータを指定する一般的な理由は, AP を参照する JSB ルーチンを呼び出すためです。 このような参照では,コンパイラは引数リストが最後の .CALL_ENTRY ルーチンでホーミングされていると仮定し, FP ベースの参照を使用します。この仮定は常に正しいとは限らないため, .JSB_ENTRY ルーチンの内部で AP が使用されると,コンパイラは情報メッセージを報告します。

コンパイラが報告する情報メッセージを抑制したい場合は,両方の引数を使用します。

引数のうちのどちらかまたは両方を省略した場合,ホーミングが必要なコードをコンパイラが見つけると,コンパイラの処理内容を示すメッセージが表示されます。これを参考に,引数を追加したり, max_args 引数の値を変更するなど,コードに対して必要な変更を行います。

home_args=TRUE だけを指定すると,次のメッセージが表示されます。

AMAC-W-MAXARGEXC, MAX_ARGS exceeded in routine routine_name, using n

このメッセージが表示されるのは,ホーミングを明示的に指示しているにもかかわらず, max_argsで引数の数を指定していないためです。明示的な引数参照が見つからない場合は, OpenVMS Alpha システムでは 6 個, OpenVMS I64 システムでは 8 個のロングワードが割り当てられます。明示的な引数参照が見つかった場合は,見つかった最大の引数参照と同じ数のロングワードが割り当てられます。 (このメッセージは,ホーミング対象としてコンパイラが見つけた引数の数よりも小さな数を max_args の値として指定した場合にも出力されます。)

max_args だけを指定した場合,ホーミングが必要な参照が見つかると,次のメッセージが出力されます。

AMAC-I-ARGLISHOME, argument list must be homed in caller 

どちらの引数も指定していないときに,ホーミングが必要な参照が見つかると,次のメッセージが出力されます。

AMAC-I-ARGLISHOME, argument list must be homed in caller 
AMAC-I-MAXARGUSE, max_args value used for homed arglist is n

ここで n は,コンパイラが検出した,参照されている引数の最大数を表します。

2.4.2 変更されたレジスタの保存

仕様どおりに作成された VAX MACRO CALL ルーチンは,引数リストを通じてすべてのパラメータを渡し,必要なすべてのレジスタを .ENTRY 宣言のレジスタ・マスクを通じて保存します。ただし,ルーチンによってはこれらの規則に従わず,レジスタでパラメータを渡したり,ルーチン内で PUSHL や POPL などの命令を使用して,必要なレジスタの内容の保存や復元を行っている場合があります。

OpenVMS Alpha システムや OpenVMS I64 システムでは, PUSHL や POPL を使用してレジスタの保存や復元を行っても,レジスタの下位 32 ビットしか保存されないため,これらの命令を使用するだけでは不十分です。レジスタの破壊を防ぐために,コンパイラは,レジスタ保存マスクで指定されたレジスタに加え,ルーチン内で変更されるすべてのレジスタ (R0と R1 を除く) の 64 ビット全体の値を自動的に保存および復元します。これは,呼び出されるルーチンからの出力値を返すために任意のレジスタを使用しても,その目的は達成できないことを意味します。出力は標準の引数リストで渡すか,出力するレジスタを, .CALL_ENTRY 宣言の outputパラメータで宣言する必要があります ( 第 2.6 節 を参照)。 OpenVMS I64 システムでは,このようなルーチンを呼び出す場合, .CALL_LINKAGE 指示文を使用する必要があります。 I64 の呼び出し規則では,呼び出しの前後でさまざまなレジスタを保存する必要があるためです。

2.4.3 引数ポインタの変更

ルーチンが AP を変更すると,コンパイラはそのルーチン内での AP のすべての使用を R12 に変更し,このような変更をすべて報告します。このようにして引数リスト全体を参照する手法はサポートされていませんが,アドレス 0(AP) を R12 に明示的に移動し,エントリ・ポイントで home_args=TRUE を指定することで,同様の結果を得ることができます。 R12 は VAX 形式の引数リストを指します。

2.4.4 呼び出されたルーチン内での動的な条件ハンドラの設定

呼び出されたルーチン内で動的な条件ハンドラを設定するには,条件ハンドラのアドレスをフレームに格納する必要があります。コンパイラは,0(FP) を変更する .CALL_ENTRY ルーチンに対して,静的な条件ハンドラを生成します。静的なハンドラは動的なハンドラを呼び出すか,条件ハンドラのアドレスがフレームに格納されていない場合には戻ります。

OpenVMS Alpha システムでは,性能上の理由から,コンパイラは,条件ハンドラを設定するすべてのルーチンの最後に自動的に TRAPB 命令を挿入するようなことはしません。 Alpha システムでのトラップは不確定であるため,これにより,ルーチンの最後の付近にある命令でのトラップが,ルーチンのエピローグ・コードでフレーム・ポインタが変更された後で処理されたために,宣言されたハンドラでトラップが処理されないことがあります。ルーチン内で生成されるすべてのトラップを,宣言されたハンドラで処理する必要がある場合は,ルーチンの実行を終了させる RET 命令の直前に EVAX_TRAPB ビルトインを挿入します。

2.5 JSB ルーチンのエントリ・ポイントの宣言

アセンブルされた VAX MACRO コードとコンパイルされた OpenVMS Alpha および OpenVMS I64 のオブジェクト・コードでは, JSB ルーチンのパラメータは通常,レジスタで渡されます。

レジスタに書き込みを行う JSB ルーチンでは,レジスタの新しい内容を出力として呼び出し元に返すのでない場合は,これらのレジスタの内容の保存および復元を行うことがあります。しかし,VAX MACRO モジュールでは, PUSHL や POPL などの命令を実行してレジスタ内容の保存および復元を行い,レジスタ内容の下位 32 ビットのみを保存することが非常に一般的であるため,コンパイラは 64 ビット・レジスタの保存と復元をルーチンの入口と出口に追加する必要があります。

コンパイラは,使用されているレジスタ・セットを算定できますが,ルーチンの呼び出し元 (他のモジュールにある可能性もある) に関する詳しい知識がないと,どのレジスタに出力値を格納するつもりなのかを判断できません。そのため,JSB ルーチンの各エントリ・ポイントに, .JSB_ENTRY 指示文または .JSB32_ENTRY 指示文を追加して,ルーチンでのレジスタの使用方法を宣言する必要があります。

2.5.1 .JSB_ENTRY と .JSB32_ENTRY の違い

JSB のエントリ・ポイントを宣言する方法は 2 つあります。 .JSB_ENTRY 指示文は標準的な宣言であり, .JSB32_ENTRY 指示文は,ルーチンの呼び出し元が, 64 ビット・レジスタの上位 32 ビットの保護を必要としないことが分かっている場合に使用します。

.JSB_ENTRY 指示文で宣言されたルーチンでは,コンパイラはデフォルトでルーチンの入口で R0 と R1 を除く,ルーチン内で変更されているすべてのレジスタの 64 ビット全体の内容を保存し,ルーチンの出口で内容を復元します。レジスタがルーチン内で明示的に変更されていない場合は,コンパイラはルーチンの呼び出しの前後でその内容を保護しません。 第 2.6 節 に示すように, .JSB_ENTRY 指示文のレジスタ引数を使用することで,コンパイラのデフォルトの動作を変更することができます。

.JSB32_ENTRY を使用すると,コンパイラはレジスタの保存および復元を自動的に行わないため,現在の 32 ビット動作はそのままになります。コンパイラは, preserve 引数で明示的に指定されたレジスタの 64 ビット値だけを保存および復元します。

レジスタの上位 32 ビットを保護する必要がない環境でルーチンを移植する場合は, .JSB32_ENTRY 指示文を使用することをお勧めします。これにより,それぞれのルーチンでレジスタを使用しているかどうかを調べる必要がないため,コードをより迅速に移植することができます。 .JSB32_ENTRY 指示文は引数なしで指定でき,必要なレジスタの値を保護するには, 32 ビット・レジスタをプッシュ/ポップする既存のコードで十分です。

  注意
OpenVMS Alpha や OpenVMS I64 の他の言語のコンパイラでは,64 ビットの値を使用することがあります。そのため,ルーチンが別の言語から呼び出される場合や,別の言語から呼び出される別の MACRO ルーチンから呼び出される場合は, .JSB32_ENTRY は使用できません。


目次 索引

© 2012 Hewlett-Packard Development Company, L.P.