日本-日本語
日本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 コンパイラ
ポーティングおよびユーザーズ・ガイド


目次 索引



.JSB32_ENTRY を使用できる一般的な 2 つのケースがあります。

  • ユーザ・モード・アプリケーションまたは自己完結型のサブシステム全体が Macro-32 で記述されている場合は,アプリケーション全体で .JSB32_ENTRY を使用できます。

  • 別の言語,または 64 ビットのレジスタ保護が必要なソースから呼び出されるメジャー Macro-32 ルーチンが 1 つある場合で,そのルーチンがいくつかの他の Macro-32 ルーチンを呼び出している場合は, 64 ビット保護のバリアを設定できます。それには,メジャー・ルーチンで .JSB_ENTRY または .CALL_ENTRY を使用し,明示的な出力でないすべてのレジスタを保護します。このようにすれば,内部的なサブルーチンで .JSB32_ENTRY 指示文を使用できます。
    コンパイラは,デフォルトではメジャー・ルーチンで明示的に変更されているレジスタについてのみ保存および復元を行うため,すべてのレジスタを明示的に保存せずに .JSB_ENTRY または .CALL_ENTRY を使用するだけでは,バリアとして十分ではありません。 .JSB32_ENTRY を使用する内部のサブルーチンで,保護されていないレジスタが変更されることがあります。バリアを迂回するような方法で,内部のサブルーチンを呼び出すことができないことも確認してください。

  注意
.JSB32_ENTRY 指示文が使用できることが分かっていると,大幅に時間が節約できる場合があります。レジスタの上位 32 ビットが使用されている状況で .JSB32_ENTRY を使用すると,非常に分かりにくく追跡が難しいバグの原因となります。問題が発生しているルーチンの数段階上の呼び出しで 64 ビットの値が破壊されるためです。

.JSB32_ENTRY は,AST ルーチン,条件ハンドラなど,非同期に実行されるコードでは使用しないでください。



PUSHR/POPR を使用して一部のレジスタの保存と復元を行っているルーチンに .JSB_ENTRY を追加する場合があります。ルーチンの使い方によっては,いくつかのレジスタが,コンパイラにより 1 回, PUSHR/POPR によってもう 1 回,合計 2 回保存および復元されます。コードの性能がきわめて重要な場合以外はこれを最適化しないでください。コンパイラはこの状況検出し,冗長な保存と復元をなくそうとします。

2.5.4 JSB ルーチン内での動的な条件ハンドラの設定

.JSB_ENTRY ルーチン内に 0(FP) を変更するコードがあると,コンパイラによってエラーが出力されます。

2.6 ルーチンのレジスタ使用の宣言

エントリ・ポイント指示文 .CALL_ENTRY,.JSB_ENTRY,.JSB32_ENTRY, .CALL_LINKAGE ( OpenVMS I64 のみ), .USE_LINKAGE ( OpenVMS I64 のみ), .DEFINE_LINKAGE ( OpenVMS I64 のみ) では,以下の 4 つのレジスタ宣言引数を指定することができます。

  • input

  • output

  • scratch

  • preserve

これらのレジスタ引数は,ルーチン内でのレジスタの使われ方を記述し,ルーチンをコンパイルする方法をコンパイラに指示するために使用します。以下の目的でレジスタ引数を使用できます。

  • コンパイラのデフォルトのレジスタ保護動作を変更するため ( 第 2.4.2 項 および 第 2.5.1 項 を参照)

  • コンパイラが使用できる一時レジスタがないことを示すため

  • ルーチンでのレジスタの使われ方を文書化するため

  注意
OpenVMS Alpha システムのみ: /OPTIMIZE=VAXREGS を指定して VAX レジスタを一時レジスタとして使用する場合,暗黙的に使用しているレジスタが一時レジスタとして使用されないように, input 句および output 句を使用して,そのようなレジスタの使用をすべて宣言する必要があります。この最適化が有効になっていると,コンパイラは,明示的に宣言されていないすべてのレジスタを一時レジスタとして使用します。



input 引数は,ルーチンが入力値を受け取るレジスタを示します。ルーチン自身はレジスタの内容を入力値として使用せず,それを使用するルーチンを呼び出す場合もあります。これは,パススルー入力テクニックと呼ばれ,呼び出される側のルーチンもルーチン・エントリ・マスクでそのレジスタを input として宣言する必要があります。

input 引数を指定しても,コンパイラのデフォルトのレジスタ保護動作に影響はありません。 input 引数のみに指定されたレジスタでも,コンパイラによって 第 2.4.2 項 および 第 2.5.1 項 で説明したように扱われます。レジスタが入力として使用されているときに,デフォルトの保護動作を変更したい場合は, input 引数に加えて, output 引数,preserve 引数, scratch 引数のいずれかでもこのレジスタを指定する必要があります。

input 引数は,ルーチンの入口で,指定されたレジスタに意味がある値が格納されており,コンパイラがそのレジスタの最初の使用を検出する前であっても,そのレジスタを一時レジスタとして使用できないことをコンパイラに対して通知します。通常,コンパイラは VAX レジスタ (R2 〜 R12) を一時レジスタとして使用しないため,input 引数にレジスタを指定すると,以下の 2 つの場合にコンパイラの一時レジスタの使用が影響を受けます。

  • OpenVMS Alpha システムのみ: 最適化オプション VAXREGS を使用している場合。この最適化を有効にすると, VAX MACRO コードで明示的に使用されていないすべての VAX レジスタをコンパイラが一時レジスタとして使用できるようになります。なお,.JSB32_ENTRY 指示文では,VAXREGS 最適化を使用した場合,コンパイラは常にすべての VAX レジスタが入力として使用されていると仮定します。そのため,VAX レジスタを input 引数に指定し,コンパイラの一時レジスタとして使用されないようにする必要はありません。

  • Alpha または Itanium のレジスタのいずれか (R13 以降) を明示的に使用している場合。

上記のいずれかのケースで,入力として使用されているレジスタを input 引数に指定しないと,そのレジスタはコンパイラによって一時レジスタとして使用され,入力値が壊れてしまいます。

最適化オプション VAXREGS を使用しておらず, Alpha や Itanium のレジスタも使用していない場合は,入力マスクはルーチンの文書化のためにのみ使用されます。

2.6.2 エントリ・ポイントのレジスタ宣言の output 引数

output 引数は,ルーチンがその呼び出し元に返す値を格納するレジスタを示します。多くの場合はそのルーチン自体がレジスタを変更しますが,出力値を代入する別のルーチンをそのルーチンが呼び出す場合もあります。これはパススルー出力テクニックと呼ばれ,呼び出される側のルーチンもそのルーチン・エントリ・レジスタ・セットでそのレジスタを output として宣言する必要があります。

この引数を使用することで,ルーチンの中で変更されるレジスタの自動的な保護が禁止されます。この引数に指定されているレジスタは,ルーチンによって変更されている場合でも, .CALL_ENTRY ルーチンや .JSB_ENTRY ルーチンで保護されません。

output 引数は,コンパイラに対し,ルーチンの出口で,指定されたレジスタに意味のある値が格納されており,コンパイラが最後にそのレジスタの使用を検出した後でも,そのレジスタを一時レジスタとして使用できないことを知らせます。通常,コンパイラは VAX レジスタ (R2 〜 R12) を一時レジスタとして使用しないため,output 引数にレジスタを指定すると,以下の 2 つの場合にコンパイラの一時レジスタの使用が影響を受けます。

  • OpenVMS Alpha システムのみ: 最適化オプション VAXREGS を使用している場合。この最適化を有効にすると, VAX MACRO コードで明示的に使用されていないすべての VAX レジスタをコンパイラが一時レジスタとして使用できるようになります。なお,.JSB32_ENTRY 指示文では,VAXREGS 最適化を使用した場合,コンパイラは常にすべての VAX レジスタが出力として使用されていると仮定します。そのため,VAX レジスタを output 引数に指定し,コンパイラの一時レジスタとして使用されないようにする必要はありません。

  • Alpha または Itanium のレジスタのいずれか (R13 以降) を明示的に使用している場合。

上記のいずれかのケースで,出力として使用されているレジスタを output 引数に指定しないと,そのレジスタはコンパイラによって一時レジスタとして使用され,出力値が壊れてしまいます。

.JSB32_ENTRY ルーチンでは,デフォルトではどのレジスタも保存されないため, output 引数はコードの文書化のためだけに使用されます。

OpenVMS Alpha システムのみ: VAXREGS の最適化では,すべてのレジスタは出力であるものと見なされるため, output 引数はコードの文書化のためにのみ使用されます。

2.6.3 エントリ・ポイントのレジスタ宣言の scratch 引数

scratch 引数は,ルーチンの中で使用しているものの,ルーチンの入口と出口で保存および復元をする必要がないレジスタを示します。ルーチンの呼び出し元は,これらのレジスタに出力値が格納されることを期待せず,レジスタが保護されることも期待しません。

この引数を使用すると,ルーチン内で変更されるレジスタが保護されなくなります。この引数に指定されているレジスタは,ルーチン内で変更される場合でも保護されません。

scratch 引数は,コンパイラの一時レジスタの使用にも関係します。レジスタ R13 以降がルーチンのソース・コードで使用されていなければ,コンパイラはこれらのレジスタを一時レジスタとして使用します。 OpenVMS Alpha システムと OpenVMS I64 システムでは, R13 〜 R15 が変更される場合は保護する必要があるため,コンパイラはこれらのレジスタを使用する場合には保護します。

しかし,これらのレジスタが scratch レジスタ・セット宣言に指定されている場合は,コンパイラは,一時レジスタとしてそれを使用する場合に保護しません。その結果,これらのレジスタは,ルーチンのソースで使用されていなくても, scratch セットに指定されていれば,ルーチンの出口では壊れている可能性があります。 VAXREGS による最適化を使用した場合は (Alpha システムのみ),これはレジスタ R2 〜 R12 にも適用されます。

.JSB32_ENTRY ルーチンでは,R2 〜 R12 はデフォルトでは保存されないため, scratch 宣言に指定しても,文書化の意味しかありません。

2.6.4 エントリ・ポイントのレジスタ宣言の preserve 引数

preserve 引数は,ルーチン呼び出しの前後で保護する必要があるレジスタを指示します。これには,変更され, 64 ビットの内容全体を保存および復元する必要があるレジスタだけを含める必要があります。

preserve 引数を指定すると,コンパイラの .CALL_ENTRY 指示文または .JSB_ENTRY 指示文の処理によってレジスタが自動的に保護されるかどうかにかかわらずレジスタは保護されます。 .JSB32_ENTRY ルーチンでレジスタの 64 ビット全体を保存および復元する唯一の方法でもあります。 R0 と R1 はスクラッチ・レジスタであるため,ルーチンのエントリ・ポイントで preserve 引数に指定しないかぎり,コンパイラはこれらのレジスタの保存と復元を行いません。

この引数は, output 引数と scratch 引数より優先されます。 preserve 引数と output 引数または scratch 引数の両方にレジスタを指定すると,コンパイラはレジスタを保護しますが,次の警告を出力します。

%AMAC-W-REGDECCON, register declaration conflict in routine A 

preserve 引数は,コンパイラの一時レジスタの使用には影響を与えません。

2.6.5 レジスタ・セットを指定するためのヘルプ

コンパイラを起動する際,コマンド行で /FLAG=HINTS を指定すると,ルーチンのエントリ・ポイントに対してレジスタ・セットを構成するのに役立つメッセージが表示されます。コンパイラが出力するヒントの中には,以下の内容が出力されます。

  • ルーチンの入力として使用されている可能性があるレジスタ。ただし,意図していないレジスタが表示されることがあります。レジスタに書き込む前に読み込むと,ここで出力されます。

  • 出力値として使用されている可能性があるレジスタ。レジスタに書き込んだ後に読み込みを行っていないと,そのレジスタは出力値として使用されている可能性があるレジスタの一覧に追加されます。これも,意図していないレジスタが表示されることがあります。

  • エントリ・ポイントの preserve 引数に指定されておらず,コンパイラが保存と復元を行うレジスタ。

.CALL_ENTRY,.JSB_ENTRY,および .JSB32_ENTRY のレジスタ引数に,ルーチンのテキスト・ヘッダに記述されているルーチンのインタフェースを反映させることをお勧めします。レジスタ引数 inputoutputscratch,および preserve は,できるだけすべてのルーチンで宣言してください。引数を指定するのは,宣言するレジスタがある場合だけでかまいません (たとえば,input=<> は必要ありません)。

2.7 ローカル・ルーチン間での分岐

あるルーチンの本体から,同じモジュールおよび psect にある別のルーチンの本体に分岐することができます。しかし,両方のルーチンでオーバヘッドが増えることになるため,コンパイラによって情報レベルのメッセージが出力されます。

  注意
コンパイラは $EXIT の呼び出しをルーチンの終了として認識しません。ルーチンを終了させるには, $EXIT の後に RET または RSB のうち適切なものを追加してください。

CALL ルーチンが,RSB を実行するコード・パスに分岐する場合,エラー・メッセージが出力されます。このような CALL ルーチンは,修正しないと,実行時にエラーになります。

JSB ルーチンが,RET 命令を実行するコード・パスに分岐し, JSB ルーチンがレジスタを保護する場合,情報メッセージが出力されます。この構造は実行時に動作しますが, JSB ルーチンによって保存されたレジスタは復元されません。

コード・パスを共用する複数のルーチンのレジスタ宣言が異なっていると,レジスタの復元は条件付きで行われます。すなわち,ルーチンの入口で保存されるレジスタはどちらのルーチンでも同じですが,レジスタが復元されるかどうかは,どちらのエントリ・ポイントが実行されたかによって変わります。

以下に例を示します。

rout1: .jsb_entry output=r3 
            movl    r1, r3          ! R3 is output, not preserved 
            movl    r2, r4          ! R4 should be preserved 
            blss    lab1 
            rsb 
    
rout2:  .jsb_entry                  ! R3 is not output, and 
            movl    #4, r3          ! should be auto-preserved 
            movl    r0, r4          ! R4 should be preserved 
lab1:       clrl    r0 
            rsb 

どちらのルーチンでも,ルーチンの入口で R3 は保存レジスタに含まれます。しかしルーチンの出口では, R3 を復元する前にマスク (同様に入口で保存されます) がテストされます。 R4 はどちらのエントリ・ポイントでも復元される必要があるため, R4 の復元の前にはマスクはテストされません。

コードを共用する 2 つのルーチンで書き込みが行われるレジスタを,一方では scratch として宣言し他方では宣言しないと,保存と復元を行うよりもコストが高くなります。この場合,両方で scratch として宣言するか,一方のルーチンで保護が必要な場合は,両方で preserve として宣言します。

2.8 例外エントリ・ポイントの宣言 ( OpenVMS Alpha のみ)

付録 B で説明するとおり, .EXCEPTION_ENTRY 指示文は,例外サービス・ルーチンのエントリ・ポイントを示します。 .EXCEPTION_ENTRY 指示文は,以下のような割り込みを扱うルーチンのエントリ・ポイントを宣言するために使用します。

  • インターバル・クロック

  • プロセッサ間割り込み

  • システムとプロセッサの訂正可能なエラー

  • 電源障害

  • システムとプロセッサのマシン・アボート

  • ソフトウェア割り込み

ルーチンの入口で, R3 にはプロシージャ記述子のアドレスが格納されている必要があります。ルーチンは REI 命令で終了する必要があります。

例外エントリ・ポイントで,割り込みディスパッチャは,レジスタ R2 〜 R7,PC,PSL をスタックにプッシュします。これらのレジスタの内容にアクセスするには, .EXCEPTION_ENTRY 指示文で stack_base 引数を指定します。コンパイラは, stack_base に指定したレジスタに SP の値を設定するコードをルーチンの入口に生成し,例外サービス・ルーチンがこのレジスタを使用して,スタック上のレジスタの値を使用できるようにします。

コンパイラは,ルーチンで使用されているその他すべてのレジスタを自動的に保存して復元します。さらに,サービス・ルーチンが CALL 命令または JSB 命令を実行する場合, R0 と R1 を含むすべてのスクラッチ・レジスタが自動的に保存および復元されます。

  注意
フレームの 0(FP)にアドレスを格納することで設定されるエラー処理ルーチンは,.EXCEPTION_ENTRY ルーチンではありません。このようなエラー・ハンドラは,.CALL_ENTRY ルーチンとして宣言し, RET 命令で終了する必要があります。


目次 索引

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