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


目次 索引

第 2 章
MACRO コンパイラのプラットフォームごとの動作

OpenVMS システムの MACRO コンパイラは, VAX MACRO ソース・コードを OpenVMS VAX から OpenVMS Alpha や OpenVMS I64 に容易に移植できるように設計されています。本書で説明する制限やガイドラインに従った VAX MACRO コードであれば,コンパイラは,オリジナルの VAX MACRO ソースの意味を保ち, OpenVMS Alpha または OpenVMS I64 の呼び出し規則に従った, OpenVMS Alpha または OpenVMS I64 の正しいオブジェクト・モジュールを生成します。

この章のトピックは以下のとおりです。



2.1 Alpha と Itanium のレジスタの使用

OpenVMS Alpha システムと OpenVMS I64 システムには, 32 個の整数レジスタ R0 〜 R31 があります。 OpenVMS Alpha コンパイラによって生成されたコードは, Alpha のレジスタ R0 〜 R12 を,VAX のレジスタであるかのように使用します。また, OpenVMS I64 コンパイラは, VAX のレジスタを,対応する Itanium のレジスタに自動的にマッピングします。そのため,VAX MACRO コードのこれらレジスタを使用している箇所 (たとえば, JSB ルーチンに対する入力として使用している場合など) は,変更しなくても正しくコンパイルされます。 VAX MACRO の命令 (MOVL や ADDL など) は,演算に関係する Alpha または Itanium のレジスタの下位 32 ビットを使用します。コンパイラは,符号拡張された 64 ビットの値をレジスタに保持します。

レジスタ R13 以降も,OpenVMS Alpha または OpenVMS I64 のオブジェクト形式にコンパイルされる VAX MACRO コードで使用できます。これらのレジスタを使用する場合には,以下の制限を確認してください。

  • 通常,既存の VAX MACRO コードはレジスタ R0 〜 R11 だけを使用し, R12 〜 R14 は,それぞれ引数ポインタ (AP),フレーム・ポインタ (FP),スタック・ポインタ (SP) として定義されています。コンパイラは,AP,FP,SP の正規の使用を, VAX のレジスタと同様の機能を持つ Alpha または I64 のレジスタへの参照としてコンパイルします。 VAX MACRO ソースが AP をスクラッチ・レジスタとして参照している場合は,コンパイラはこの参照を R12 に対する参照に変換します。これが望ましくない場合は,別のスクラッチ・レジスタを使用するようにコードを変更する必要があります。

  • コンパイラが VAX MACRO ソース内で R12,R13,R14 への参照を検出すると, AP,FP,SP に相当する Alpha または I64 のレジスタへの参照に変換しません。代わりに,対応する Alpha の整数レジスタへの参照と見なします。

  • R13 以降を使用するコードは,VAX MACRO アセンブラでアセンブルできません。そのため,OpenVMS Alpha または OpenVMS I64 の条件付きとするか, OpenVMS Alpha または OpenVMS I64 専用のモジュールにします。

  • ビルトイン EVAX_LDQ と EVAX_STQ を使用することで,レジスタの 64 ビット全体にアクセスできます。この機能については, 付録 C を参照してください。

  • OpenVMS Calling Standard で規定されているように,特定の使用目的を持ったレジスタを参照する場合には,特に注意する必要があります。

  • OpenVMS Calling Standard で規定されているように, R16 以降のレジスタはスクラッチ・レジスタです。ルーチン呼び出しにまたがって値が保持されると仮定しないでください。

  • ルーチンのソース・コードでレジスタ R13 以降が使用されていない場合,コンパイラはこれらのレジスタを一時的なレジスタとして使用します。 R13 〜 R15 を使用する場合は,保存と復元が行われます。

  • Alpha システムでは,保存したレジスタはスタックに書き込まれます。 I64 システムでは,保存したレジスタはレジスタ 32 〜 127 にコピーされます。



2.2 Itanium アーキテクチャ,呼び出し規則,レジスタ・マッピング

Itanium アーキテクチャと OpenVMS I64 には, Alpha アーキテクチャと OpenVMS Alpha に比べて重要な違いがいくつかあります。

OpenVMS I64 システムでは,32 個の整数レジスタ R0 〜 R31 があり, R0 は読み取り専用のレジスタで,0 を保持しています。これに対し OpenVMS Alpha では, R31 は読み書きレジスタで,0 を保持しています。

また, OpenVMS I64 の呼び出し規則は, Intel の呼び出し規則と互換性を持つように作成されており, OpenVMS Alpha の呼び出し規則とは大きく異なっています。たとえば, OpenVMS I64 の標準の戻りレジスタは R8/R9 ですが, OpenVMS Alpha では R0/R1 です。 OpenVMS I64 の呼び出し規則では, R1 は GP (グローバル・ポインタ) として予約されており,標準化された FP (フレーム・ポインタ) が含まれていません。また,呼び出しにまたがって保持されるのは R4 〜 R7 だけです。これに対し OpenVMS Alpha では,R2 〜 R15 が保持されます。

Macro-32 ソース・コードは, OpenVMS VAX と OpenVMS Alpha の呼び出し規則を念頭に記述されているため,既存のコードを OpenVMS I64 のコンパイラで変更なしにコンパイルできるようにするために,コンパイラはいくつかの変換を行います。

まず,コンパイラは Macro-32 ソース・プログラムのレジスタを I64 ハードウェア上の異なるレジスタにマッピングします。これにより既存のプログラムが "MOVL SS$_NORMAL, R0" を使用できるようになり,生成されたコードが呼び出し規則どおりに R8 に値を返すようになります。 表 2-1 に, OpenVMS VAX / OpenVMS Alpha から OpenVMS I64 へのレジスタのマッピングを示します。

表 2-1 OpenVMS VAX / OpenVMS Alphaから OpenVMS I64へのレジスタ・マッピング
ソース・コード中の OpenVMS VAX / OpenVMS Alpha のレジスタ 生成されたコードで使用される OpenVMS I64 のレジスタ
   
R0 R8
R1 R9
R2 R28
R3 R3
R4 R4
R5 R5
R6 R6
R7 R7
R8 R26
R9 R27
R10 R10
R11 R11
R12 R30
R13 R31
R14 R20
R15 R21
R16 R14
R17 R15
R18 R16
R19 R17
R20 R18
R21 R19
R22 R22
R23 R23
R24 R24
R25 R25
R26 Itanium スタック汎用レジスタ
R27 Itanium スタック汎用レジスタ
R28 Itanium スタック汎用レジスタ
R29 R29
R30 R12
R31 R0

レジスタのマッピングは,呼び出しにまたがって保護されるレジスタ,呼び出しにまたがって保護されないレジスタ,呼び出し時や戻り時に値が変わる揮発性レジスタなど,レジスタの特性に基づいて慎重に選択されています。

OpenVMS Alpha では,AP に対する Macro-32 の参照は,引数がスタックに格納されているかどうかに応じて,コンパイラによって適切な場所にマッピングされます。 FP への参照をサポートするため,コンパイラは必要に応じて FP の値を作成します。 OpenVMS VAX および OpenVMS Alpha と同様に条件ハンドラを確立するために,コンパイラは 0(FP) への参照をサポートします。

本書の他の箇所に記載されているレジスタ番号は,その番号の VAX/Alpha レジスタを参照しています。実際の Itanium レジスタへのマッピングは, Macro-32 ソース・コード (およびコンパイラの大半の部分) では意識する必要がありません。

コンパイラには,マッピング・テーブルを介さずに Itanium レジスタに直接アクセスするための構文がありません。

コンパイラによる自動的なレジスタのマッピングにより,ほとんどの Macro-32 プログラム (Alpha のレジスタ R16 〜 R31 にアクセスするものを含む) は,変更なしでコンパイルできます。

ただし, OpenVMS Alpha でのルーチン・パラメータとしてレジスタ R16 〜 R21 を使用している場合は, OpenVMS I64 へのポータビリティがありません。 CALL にパラメータを渡すには PUSHL を使用し,呼び出された側のルーチンでは 4(AP),8(AP) などを使用してそのパラメータを参照してください。コンパイラは, VAX のオペランドで暗黙的に使用されているスタック参照の代わりに,正しいレジスタ参照を生成します。

OpenVMS I64 システムでは, OpenVMS Alpha システム上で Alpha の命令に直接アクセスするためのビルトイン EVAX_* の多くが引き続きサポートされます。これらのビルトインでは,同じ論理演算を行う Itanium の命令が生成されます。 I64 システムでもサポートされる EVAX_* ビルトインの一覧については, 付録 C を参照してください。

2.3 ルーチンの呼び出しと宣言

OpenVMS Calling Standard では, OpenVMS VAX システム, OpenVMS Alpha システム,および OpenVMS I64 システムに対して,大きく異なる呼び出し規約が規定されています。

OpenVMS VAX システムでは, 2 種類の呼び出し形式 CALL と JSB があり, 5 つの命令 CALLS,CALLG,JSB,BSBW,および BSBB があります。 CALL 命令は,戻り情報,保存されたレジスタ,その他のルーチン情報が格納されるフレームをスタック上に作成します。 CALL 命令に対するパラメータは,スタック上 (CALLS) またはその他の場所 (CALLG) にある連続したロングワード・メモリ位置に格納して渡されます。 JSB 命令では,戻りアドレスがスタック上に格納されます。どちらの呼び出し形式でも,呼び出し命令のハードウェア処理によってこれらすべての機能が提供されます。

OpenVMS Alpha システムでは,呼び出し形式は 1 つしかなく,サブルーチン呼び出し命令も JSR だけです。パラメータを受け取るルーチンでは,最初の 6 つのパラメータが R16 〜 R21 で渡され,パラメータの個数が R25 で渡されます。残りのパラメータは,スタック上でクォドワードとして渡されます。 JSR 命令のハードウェアによる実行では,単に制御をサブルーチンに渡し,指定されたレジスタに戻りアドレスを格納します。スタック領域を割り当てることも,呼び出しフレームを作成することも,パラメータ操作を行うこともしません。これらすべての機能は,呼び出し側のルーチンで行うか,呼び出される側のルーチンで行う必要があります。

OpenVMS I64 システムでは,呼び出し形式は 1 つしかなく,サブルーチン呼び出し命令も br.call だけです。パラメータを受け取るルーチンでは,最初の 8 つのパラメータは R32 〜 R39 で渡され,パラメータの個数が R25 で渡されます。残りのパラメータは,スタック上でクォドワードとして渡されます。 ( OpenVMS I64 上の MACRO コンパイラでは,レジスタ・スタックを直接操作することはできず, R31 より大きな番号のレジスタにアクセスするための構文もありません。) br.call 命令のハードウェアによる実行では,単に制御をサブルーチンに渡し,指定されたレジスタに戻りアドレスを格納し,ハードウェア・レジスタ・スタックを調整します。スタック領域を割り当てることも,呼び出しフレームを作成することも,パラメータ操作を行うこともしません。これらすべての機能は,呼び出し側のルーチンで行うか,呼び出される側のルーチンで行う必要があります。

コンパイラは, OpenVMS Calling Standard に準拠しつつ,さまざまな VAX MACRO 命令の機能をエミュレートするコードを生成する必要があります。そのためには,呼び出し命令で入力パラメータを操作するコードと,ルーチン自体のエントリ・ポイントでスタック・フレームなどのコンテキストを作成するための特別なコードが必要になります。

コンパイラは,宣言されたルーチンの一部となっているソース命令に対するコードだけを生成します。コンパイラが正しいリンケージ情報と正しいルーチン・コードを生成するように, VAX MACRO ソースのエントリ・ポイントにコンパイラ指示文を挿入する必要があります。

2.3.1 リンケージ・セクション( OpenVMS Alpha のみ)

Alpha システムでは,すべての外部 (モジュール外) 参照は リンケージ・セクションを通じて行われます。リンケージ・セクションは,以下のものが格納されたプログラム・セクション (psect) です。

  • 外部変数のアドレス

  • コード・ストリームに直接格納できない大きな定数

  • リンケージ・ペア

  • プロシージャ記述子

リンケージ・ペアは,外部モジュールを呼び出すときに使用するデータ構造です。リンケージ・ペアには,呼び出されるプロシージャ記述子のアドレスと,エントリ・ポイント・アドレスが格納されます。リンケージ・ペアは呼び出し側のリンケージ・セクションにあります。そのため,あるルーチンに対して,呼び出し側のリンケージ・セクションに 1 つずつ,いくつものリンケージ・ペアがあります。モジュール・ローカルな呼び出しの場合は,呼び出される側のフレーム記述子をコンパイラが直接参照できるため,リンケージ・ペアは使用されません。

プロシージャ記述子は,レジスタとスタックの使用など,ルーチンに関する基本的な情報を提供するデータ構造です。各ルーチンには固有のプロシージャ記述子があり,リンケージ・セクションの中にあります。通常,プロシージャ記述子は,実行時にはアクセスされません。主に,例外が発生した場合や,デバッガなどによって,フレームを解釈するために使用されます。

これらを含む各種のデータ構造についての詳細は, OpenVMS Calling Standard を参照してください。

2.3.2 プロローグ・コードとエピローグ・コード

VAX のサブルーチンの動作をまねるために,コンパイラは各ルーチンの入口と出口でコードを生成する必要があります。このコードは,VAX ハードウェアによって実行される機能をエミュレートし,プロローグ・コードおよびエピローグ・コードと呼ばれます。

プロローグ・コードでは,コンパイラは,必要なコンテキストを保存するために,スタック領域 (および OpenVMS I64 システムではスタック汎用レジスタ) を割り当てる必要があります。これには,ルーチンが保護しなければならないレジスタの保存と,戻りアドレスの保存が含まれます。 CALL ルーチンの場合は,新しいスタック・フレームの作成と,フレーム・ポインタ (FP) の変更も含まれ ( OpenVMS Alpha システムと OpenVMS I64 システムで必要に応じて),さらに入力パラメータの操作と保存が含まれることもあります ( 第 2.4 節 を参照)。

エピローグ・コードでは,コンパイラは必要なレジスタ,スタック・フレーム情報,戻りアドレスを復元し,スタックを元の位置まで切り捨てます。

2.3.3 エントリ・ポイントの宣言が必要な場合

CALLS,CALLG,JSB,BSBW,BSBB 命令のいずれかのターゲットとして使用される可能性があるコード・ラベルは,エントリ・ポイントとして宣言する必要があります。また,以下の条件に該当するコード・ラベルは,すべて .JSB_ENTRY 指示文または .JSB32_ENTRY 指示文を使用して,エントリ・ポイントとして宣言する必要があります。

  • ラベルが,グローバルな (モジュールにまたがった) JMP 命令, BRB 命令,または BRW 命令のターゲットとなる可能性がある場合。

  • ラベルが,不確定な分岐 (BRB#@(R10) など) のターゲットとなる可能性があり,参照とラベルが同じモジュール内にある場合でもラベルのアドレスが R10 に格納されている場合。

  • 現在のモジュールからラベルがアクセスされるかどうかにかかわらず,ラベルのアドレスがレジスタまたはメモリ位置に格納される場合。

I64 と Alpha の OpenVMS の呼び出し規則では,不確定なコード・アドレスに直接アクセスする手段は提供されていません。そのようなアクセスは,すべてルーチンとコード・アドレスを記述するプロシージャ記述子を通じて実現されます。コード・ラベル・アドレスが格納されるときには,コンパイラはそのアドレスが現在のモジュールからだけ参照されるのか,別の MACRO モジュールや別の言語で記述された別のモジュールからも参照されるのかが分かりません。ソース命令がコード・アドレスを格納するときには必ず, MACRO コンパイラは,他のコードがそのコードに正しくアクセスできるように,代わりにそのコード・アドレスのプロシージャ記述子アドレスを格納します。プロシージャ記述子が存在するために,ラベルをエントリ・ポイントとして宣言する必要があります。格納されているアドレスを分岐先として使用する際,コンパイラはそのアドレスがどこから来たかを知らないため,格納されているアドレスを常にプロシージャ記述子のアドレスであると見なして,その記述子を使用してルーチンに制御を渡します。

OpenVMS I64 システムは, OpenVMS Alpha システムと同じように振る舞いますが,唯一の違いは,呼び出し規則では用語"関数記述子"が使用され,関数記述子はリンカによって作成される点です。


目次 索引

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