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


目次 索引

第 5 章
MACRO の 64 ビット・アドレッシングのサポート

この章では,MACRO コンパイラとそれに関連する構成要素による 64 ビット・アドレッシングのサポートについて説明します。

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



5.1 64 ビット・アドレッシングの構成要素

MACRO コンパイラでは,64 ビット・アドレッシングをサポートする構成要素が提供されています。

64 ビット・アドレッシングは, OpenVMS Alpha または OpenVMS I64 に移植したコードでのみ使用してください。 OpenVMS Alpha または OpenVMS I64 上で新たに開発する場合は,高級言語を使用することをお勧めします。

信頼性が高く保守が簡単なコードを生成できるように提供されている,修飾子,マクロ,指示文,ビルトインを使用して, 64 ビット・アドレッシングをコード中で明示的に行う必要があります。

表 5-1 に, MACRO プログラミングでの 64 ビット・アドレッシングのサポートを提供する構成要素を示します。

表 5-1 64 ビット・アドレッシング用の構成要素
構成要素 説明
$SETUP_CALL64 呼び出し手順を初期化するマクロ
$PUSH_ARG64 引数のプッシュ相当の処理を実行するマクロ
$CALL64 対象ルーチンを呼び出すマクロ
$IS_32BITS 64 ビット値の下位 32 ビットの符号拡張をチェックするマクロ
$IS_DESC64 記述子が 64 ビット形式の記述子かどうかを判断するマクロ
QUAD=NO/YES 64 ビット仮想アドレスをサポートするためのページ・マクロのパラメータ
/ENABLE=QUADWORD 64 ビット・アドレスの計算を含むように拡張された QUADWORD パラメータ
.CALL_ENTRY QUAD_ARGS=TRUE|FALSE QUAD_ARGS=TRUE|FALSE。引数リストに対するクォドワード参照の有無を示す ( 第 5.3 節 を参照)
.ENABLE QUADWORD
.DISABLE QUADWORD
64 ビット・アドレスの計算を含むように拡張された QUADWORD パラメータ
EVAX_SEXTL 64 ビット値の下位 32 ビットを符号拡張してデスティネーションに格納するビルトイン
EVAX_CALLG_64 可変サイズの引数リストを使用した 64 ビット呼び出しをサポートするためのビルトイン
$RAB64 および $RAB64_STORE 64 ビット・アドレス空間のバッファを使用するための RMS マクロ



5.2 64 ビット値の受け渡し

64 ビット値を渡すために使用する方法は,引数リストのサイズが固定か可変かによって変わります。ここでは,これらの方法について説明します。

5.2.1 固定サイズの引数リストを使用した呼び出し

固定サイズの引数リストを使用した呼び出しでは, 表 5-2 に示すマクロを使用します。

表 5-2 固定サイズの引数リストを使用した 64 ビット値の受け渡し
使用する手順 使用するマクロ
1. 呼び出し手順の初期化 $SETUP_CALL64
2. 呼び出し引数の「プッシュ」 $PUSH_ARG64
3. 対象ルーチンの呼び出し $CALL64

これらのマクロの使用例を以下に示します。引数は逆の順序でプッシュされる点に注意してください。これは,32 ビットの PUSHL 命令を使う場合でも同様です。

MOVL           8(AP), R5         ; fetch a longword to be passed 
$SETUP_CALL64  3                 ; Specify three arguments in call 
$PUSH_ARG64    8(R0)             ; Push argument #3 
$PUSH_ARG64    R5                ; Push argument #2 
$PUSH_ARG64    #8                ; Push argument #1 
$CALL64        some_routine      ; Call the routine 

$SETUP_CALL64 マクロは,64 ビット呼び出しの状態を初期化します。 $PUSH_ARG64 や $CALL64 を使用する前に必要です。引数の数が OpenVMS Alpha では 6, OpenVMS I64 では 8 を超える場合は,このマクロはローカルな JSB ルーチンを作成します ( このルーチンは,呼び出しを実行するために呼び出されます)。そうでない場合は,引数のロードと呼び出しはインラインとなり,非常に効率が良くなります。 $SETUP_CALL64 で指定する引数カウントには,シャープ (#) は含まれないことに注意してください。 (標準的な呼び出し手順では,スタックはオクタワードでアラインされ,スタックの先頭に引数が置かれている必要があります。JSB ルーチンはこのアラインメントを手助けします。)

インライン・オプションを使用して, 6 個または 8 個を超える引数を使用した呼び出しを,ローカルな JSB ルーチンを使用せずに行うことができます。ただし,その利用には制限があります ( 付録 E を参照)。

$PUSH_ARG64 マクロは,引数を正しい引数レジスタまたはスタック領域に直接移動します。これは実際にはスタックのプッシュではなく, 32 ビット呼び出しで使用する PUSHL 命令を模したものです。

$CALL64 マクロは,引数カウント・レジスタを設定し,対象ルーチンを呼び出します。 JSB ルーチンが作成されている場合は,そのルーチンを呼び出します。プッシュした引数の数が $SETUP_CALL64 で指定した数と一致しない場合,このルーチンはエラーを報告します。 $CALL64 と $PUSH_ARG64 は, $SETUP_CALL64 がすでに呼び出されていることを確認します。

$SETUP_CALL64,$PUSH_ARG64,および $CALL64 を使用する際には,以下の点に注意してください。

  • 引数は,アラインされたクォドワードとして読み込まれます。メモリにあるロングワードを渡すには, 第 5.2.1 項 の例に示したように,レジスタに移動してからそのレジスタを $PUSH_ARG64 で使用します。同様に,渡すクォドワードがアラインされていないことが分かっている場合は,まず値をレジスタに移動します。また,(R4)[R0] のようにインデックス指定されたオペランドは, $PUSH_ARG64 で使用されるときにクォドワード・インデックスを使用して評価される点に注意してください。

  • 引数の数が OpenVMS Alpha では 6, OpenVMS I64 では 8 を超え,ローカルな JSB ルーチンが作成される場合は, $SETUP_CALL64 と $CALL64 の間での SP や AP の参照は行えません。 $PUSH_ARG64 マクロと $CALL64 マクロは,オペランドでのこれらのレジスタの使用を報告します。しかし,この範囲にある他の命令では使用できませんが,使用してもエラーは報告されません。このような場合,AP または SP ベースの引数を渡すには, $SETUP_CALL64 を呼び出す前にレジスタに移動します。

  • OpenVMS Alpha システムのみ: 引数の数が 6 を超える場合は, $SETUP_CALL64 を実行した後で R15 以降のレジスタの値が保持されていることを期待しないでください。代わりに,スクラッチ・レジスタ以外のレジスタを一時レジスタとして使用してください。たとえば,スタック領域から取り出したデータを渡したいとし,呼び出しのパラメータが 7 個以上あるとします。この場合,値をレジスタに移動する必要があります。 R28 などのスクラッチ・レジスタを使用せずに, R0 などの VAX レジスタを使用してください。 VAX レジスタがすべて使用中の場合は,R13,R14,または R15 を使用してください。

  • OpenVMS Alpha システムのみ: $SETUP_CALL64 と $CALL64 の間で R16 以降のスクラッチ・レジスタを使用できます。ただし,すでにロード済みの引数レジスタを使用しないように注意してください。引数レジスタは,R21 から R16 へ,小さいほうに向かってロードされます。そこで,呼び出しで 6 つの引数が渡されると仮定します。 $PUSH_ARG64 によって R21 がロードされるため,最初の $PUSH_ARG64 の呼び出しの後で R21 を使用するのは危険です。 $PUSH_ARG64 マクロは,オペランドがすでにロードされている引数レジスタを参照していないかをチェックします。そのようなオペランドがみつかると,コンパイラは警告を報告します。一時レジスタが必要な場合の最も安全なアプローチは,レジスタ R22 〜 R28 を使用することです。

  注意
マクロ $SETUP_CALL64,$PUSH_ARG64,および $CALL64 は,インライン・シーケンスで使用されることを意図しています。つまり $SETUP_CALL64/$PUSH_ARG64/$CALL64 シーケンスの途中に分岐したり, $PUSH_ARG64 マクロの前後で分岐したり, $CALL64 を呼び出さずにこのシーケンスから外に分岐することはできません。

$SETUP_CALL64,$PUSH_ARG64,および $CALL64 についての詳細は, 付録 E を参照してください。

5.2.2 可変サイズの引数リストを使用した呼び出し

可変サイズの引数リストを使用した呼び出しでは,以下の手順に示すように EVAX_CALLG_64 ビルトインを使用します。

  1. インメモリ引数リストを作成します。

  2. インメモリ引数リストを渡してルーチンを呼び出します。例を示します。

    EVAX_CALLG_64 (Rn), routine
    

EVAX_CALLG_64 ビルトインの引数リストは,クォドワードの引数カウントから始まる一連のクォドワードとして読み込まれます。

5.3 64 ビット引数の宣言

.CALL_ENTRY のパラメータ QUAD_ARGS=TRUE を使用し,ルーチンの引数リスト中でのクォドワード引数の使用を宣言することができます。 QUAD_ARGS パラメータがあると,コンパイラは,引数リストに対するクォドワード参照があったときに異なる動作をします。まず,通常このような参照で必要となる引数リストのホーミングを適用しません。 (ホーミングは,その定義上,引数をロングワード・スロットにパックするため,クォドワード値が格納された引数リストはホーミングできません。) また,引数リストに対するクォドワード参照では, アラインされていないメモリ参照は報告されません。

引数リスト参照自体に対して生成される実際のコードは, MOVQ のように VAX のクォドワード命令の中に参照がある場合を除いて, QUAD_ARGS 句があっても変わりません。たいていの場合,QUAD_ARGS は,クォドワード参照による引数リストのホーミングが行われないようにし,不要なアラインメント・メッセージを抑止するだけです。この抑止は,EVAX_ ビルトインと, MOVQ などの VAX のクォドワード命令の両方に適用されます。

VAX のクォドワード命令では, QUAD_ARGS 句を指定すると,EVAX_ ビルトインと同じように,クォドワード引数を実際のクォドワードとして読み込みます。次の例を考えます。

MOVQ    4(AP), 8(R2) 

QUAD_ARGS 句を指定すると,MOVQ は引数 1 の 64 ビット全体を 8(R2) の位置のクォドワードに格納します。 QUAD_ARGS 句が指定されていないと, MOVQ は引数 1 と 2 の下位ロングワードを 8(R2) の位置のクォドワードに格納します。

QUAD_ARGS は,AP ベースの遅延モードのオペランドに対して生成されるコードにも影響を与えます。実効アドレスをメモリ内の引数からロードする必要がある場合は, QUAD_ARGS が有効になっていると,ロングワードとしてではなくクォドワードとして読み込まれます。

QUAD_ARGS を使用する場合には以下の点に注意してください。

  • AP ベースのクォドワード引数リスト参照は,重なっているように見えるため,一見するとおかしいように思われます。この状況は,たとえば,FIRST_ARG,SECOND_ARG など,引数リスト・オフセットにシンボリック名を定義することで,改善することができます。ソース・コードの可読性を高めるために,引数の使用目的を示す意味のあるシンボリック名を定義することをお勧めします。また,引数レジスタの直接参照を使用し, OpenVMS Alpha システムでの最初の 6 個の引数を参照することができます。 ( OpenVMS I64 では,引数レジスタにアクセスすることはできません。) いずれにしても,QUAD_ARGS を宣言して,引数リストがホーミングされないようにすると便利です。

  • コードを共用するルーチンでは,QUAD_ARGS の設定を同じにする必要があります。同じになっていないと,コンパイラから警告メッセージが報告されます。

  • JSB ルーチンは,呼び出し元で QUAD_ARGS が宣言されていると,呼び出し元の引数リストを参照できません。 JSB ルーチン内で AP を参照するためには,最後の CALL_ENTRY の引数リストがホーミングされている必要があります。 HOME_ARGS と QUAD_ARGS は同時に使用できません。

  • QUAD_ARGS を宣言すると, $ARGn シンボルがロングワードではなくクォドワードとして定義されます (このシンボルは,コンパイラによってデバッグ・シンボル・テーブルに格納されます)。 これらのシンボルを使用することで,受け取った引数の値に容易にアクセスできるようになり,シンボリック・デバッガでデバッグする際に,レジスタ番号やスタック・オフセットの代わりに使用できます。



5.4 64 ビット・アドレス計算の指定

MACRO には,明示的なポインタ型宣言はありません。レジスタに 64 ビット・ポインタ値を作成する方法には,さまざまなものがあります。最も一般的な方法は,EVAX_LDQ ビルトインを使用して,メモリに格納されているアドレスをロードする方法と, MOVAx を使用して,特定のオペランドのアドレスを取得する方法です。

64 ビットのポインタ値をレジスタに格納したら,通常の命令で 64 ビット・アドレスにアクセスします。そのアドレスから読み込まれるデータの量は,使用する命令に依存します。次の例を考えます。

MOVL     4(R1), R0 

MOVL 命令は,R1 に 32 ビットのポインタが格納されている場合でも, 64 ビットのポインタが格納されている場合でも, R1 からオフセット 4 の位置にあるロングワードを読み込みます。

しかし,特定のアドレッシング・モードでは,実効アドレスを計算するために,算術命令の生成が必要です。 VAX との互換性のため,コンパイラはこれらをロングワード演算として計算します。たとえば, 4 + <1@33>を計算すると,シフトした値が 32 ビットを超えるため,結果の値は 4 となります。クォドワード・モードが有効な場合は,上位ビットは失われません。

バージョン 7.0 よりも前の OpenVMS Alpha に添付されていたコンパイラでは, /ENABLE=QUADWORD 修飾子 (および対応する指示文.ENABLE QUADWORD と .DISABLE QUADWORD) は,定数式の評価が実行されるモードにだけ影響がありました。 OpenVMS Alpha Version 7.0 および OpenVMS I64 では,アドレス計算にも影響を与えるように拡張されました。その結果,SxADDQ や ADDQ などのクォドワード命令でアドレスが計算されるようになりました。

モジュール全体でクォドワード演算を使用するには,コマンド行で /ENABLE=QUADWORD を指定します。特定のセクションだけにクォドワード演算を適用する場合は,指示文 .ENABLE QUADWORD と .DISABLE QUADWORD を使用してこれらのセクションを囲みます。

/ENABLE=QUADWORD を使用しても性能が低下することはありません。

5.4.1 ロングワード演算のラップ動作への依存

既存のコードが 32 ビット演算のラップ動作に依存している可能性があるため,コンパイラは,すべてのアドレス計算でクォドワード演算を使うことはできません。つまり,上位ビットが破棄されることを承知で,実際に 32 ビットをオーバフローするアドレス演算を行っている可能性があります。クォドワード・モードで計算を行うと互換性が失われます。

/ENABLE を使用して,モジュール全体のクォドワード評価を設定する前に,既存のコードの中にロングワードのラップ動作に依存している部分がないか確認してください。この確認を行うための簡単な方法はありませんが,プログラミング・テクニックとしてはめったに使用されないためコード中にコメントが記載されていることがあります。

次の Alpha の例は,ラップ動作の問題を示します。

MOVAL   (R1)[R0], R2 

R1 に値 7FFFFFFF が格納されており,R0 に 1 が格納されているとします。 MOVAL 命令は S4ADDL 命令を生成します。シフトと加算の結果 32 ビットを超えますが,格納される結果は符号拡張された下位 32 ビットです。

クォドワード演算を使用すると (S4ADDQ),次の例に示すように真のクォドワード値となります。

S4ADDL  R0, R1, R2   =>  FFFFFFFF 80000003 
S4ADDQ  R0, R1, R2   =>  00000000 80000003 

ラップ動作の問題は,インデックス・モードのアドレッシングだけに限りません。次の例を考えます。

MOVAB   offset(R1), R0 

シンボル offset がコンパイル時に定数でない場合は,この命令によって値がリンケージ・セクションから読み込まれ, R1 の値に加算されます (ADDL 命令を使用)。これを ADDQ に変更すると,値が 32 ビットを超えている場合に結果が変わります。

Itanium アーキテクチャには S4ADDL 命令に相当する命令がありませんが,コンパイラは shladd 命令と sxt4 命令を生成し,この効果をシミュレートします。


目次 索引

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