OpenVMS Alpha上で新しく開発を行う場合は,高級言語の使用をおすすめします。
64ビット・アドレッシングの修飾子,マクロ,ディレクティブ, ビルトインを使用すると,信頼性が高く管理しやすいコードを生成することができます。
コンポーネント | 説明 |
---|---|
$SETUP_CALL64 | 呼び出しシーケンスを初期化する新規マクロ |
$PUSH_ARG64 | 引数プッシュに相当する処理を行う新規マクロ |
$CALL64 | ターゲット・ルーチンを起動する新規マクロ |
$IS_32BITS | 64ビット値の下位32ビットの符合拡張をチェックする新規マクロ |
$IS_DESC64 | ディスクリプタが64ビット形式ディスクリプタか決定する新規マクロ |
QUAD=NO/YES | 64ビット仮想アドレスをサポートするためのページ・マクロの新規パラメータ |
/ENABLE=QUADWORD | QUADWORDパラメータは拡張され,64ビット・アドレス計算を含む |
.CALL_ENTRY QUAD_ ARGS=TRUE|FALSE |
QUAD_ARGS=TRUE|FALSEは引数リストへのクォドワード参照を指定する新規パラメータ |
.ENABLE QUADWORD /.DISABLE QUADWORD |
QUADWORDパラメータは拡張され,64ビット・アドレス計算を含む |
EVAX_SEXTL | 64ビット値の下位32ビットを, ターゲットに対して符合拡張する新規ビルトイン |
EVAX_CALLG_64 | 可変サイズの引数リストで 64ビット呼び出しをサポートするため新規ビルトイン |
$RAB64および$RAB64_STORE | 64ビット・アドレス空間でバッガを使用するための新規RMSマクロ |
手順 | 使用するマクロ |
---|---|
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を使用する前に必要です。引数の個数が6個を越える場合, このマクロはローカルJSBルーチンを作成し,これが起動されて呼び出しを実行します。 引数の個数が6個以下の場合,引数のロードと呼び出しはインラインで行われ, きわめて効率的です。なお,$SETUP_CALL64に指定される引数の個数には, #が含まれないことに注意してください。(これは,標準呼び出しシーケンスが, オクタワード・アライン・スタックの先頭のスタック引数の, オクタワード・アラインを求めるためです。JSBルーチンは, このアライン操作を行います。)
インライン・オプションを使用すると,ローカルJSBルーチンがなくても, 6個を越える引数を指定して呼び出しを強制的に実行できます。ただし, その使用には制限があります(詳細は 付録 Bを参照してください)。
$PUSH_ARG64マクロは,引数を正しい引数レジスタやスタック位置に直接移動します。 これは実際にはスタック・プッシュではありませんが, 32ビット呼び出しの中で使用されるPUSHL命令に似ています。
$CALL64マクロは引数カウント・レジスタを設定し,ターゲット・ルーチンを起動します。 JSBルーチンが作成された場合は,そのルーチンを終了させます。 プッシュされた引数の個数が, $SETUP_CALL64で指定された個数に一致しない場合, エラーが報告されます。 $CALL64および$PUSH_ARG64を使用する前に, $SETUP_CALL64が起動されていることを確認してください。
$SETUP_CALL64,$PUSH_ARG64,および$CALL64についての詳細は, 付録 Bを参照してください。
- 注意
- $SETUP_CALL64,$PUSH_ARG64,および$CALL64マクロは, インライン・シーケンスで使用することを目的としています。つまり, $SETUP_CALL64/$PUSH_ARG64/$CALL64シーケンスの中央に分岐したり, $PUSH_ARG64マクロの回りで分岐することはできず,シーケンスを出て $CALL64を避けることもできません。
EVAX_CALLG_64 (Rn), routine
引数リスト参照用に生成された実際のコードは, QUAD_ARGS句の指定によって変更を受けることはありません。ただし,MOVQなど VAXクォドワード命令の中で参照が行われる場合は除きます。多くの場合, 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に基づいた defferdモード・オペランドのために生成されたコードに影響を与えます。 メモリ中の引数から有効なアドレスをロードしなければならない場合に, QUAD_ARGSが有効であれば, これはロングワードではなくクォドワードとして読み込まれます。
レジスタに64ビット・ポインタ値を作成したら,通常の命令で 64ビット・アドレスにアクセスします。そのアドレスから読み込まれるデータの量は, 使用される命令によってそれぞれ異なります。次の例を考えます。
MOVL 4(R1), R0R1が含むポインタが32ビットの場合も64ビットの場合も,MOVL命令は R1からのオフセットが4の位置でロングワードを読み込みます。
しかし,特定のアドレッシング・モードでは,算術命令を生成して,
有効なアドレスを計算することを要求します。VAXとの互換性を目的として,
コンパイラはこれらをロングワード操作として計算します。たとえば,
4 +<1@33>
の結果は,シフトされた値が32ビットを越えるため,
値4となります。クォドワード・モードが有効の場合,
上位ビットが失われることはありません。
以前のバージョンのOpenVMS Alphaと共に出荷されていたコンパイラの場合, /ENABLE=QUADWORD修飾子(および対応する.ENABLE QUADWORDディレクティブと .DISABLE QUADWORDディレクティブ)は, 定数式の評価が行われるモードに影響するだけでした。OpenVMS Alpha Version 7.0 の場合,これらは拡張され,アドレス計算に影響します。この結果, SxADDQおよびADDQなどのクォドワード命令でアドレスが計算されます。
モジュール全体でクォドワード操作を使用するには,コマンド行で /ENABLE=QUADWORDを指定します。 特定のセクションにだけクォドワード操作を適用するには,該当するセクションを .ENABLE QUADWORDおよび .DISABLE QUADWORDディレクティブで囲みます。
/ENABLE=QUADWORDを使用しても,性能が低下することはありません。
/ENABLEを使用してモジュール全体に対してクォドワード評価を設定する前に, 既存のコードをチェックして,ロングワードの折り返しへの影響を確認してください。 これを簡単に行うことはできませんが, プログラミング手法としてこれはきわめて珍しいもので, コードの外側で呼び出されている可能性もあります。
次の例は折り返しの問題を示しています。
MOVAL (R1)[R0], R2R1は値7FFFFFFFを含み,R0は1を含むとします。 MOVAL命令はS4ADDL命令を生成します。 シフトと追加によって32ビットを越えますが, 保存される結果は符号拡張された下位の32ビットです。
クォドワード計算が使用されると(S4ADDQ),次の例に示すように, 本当のクォドワード値が算出されます。
S4ADDL R0, R1, R2 => FFFFFFFF 80000003 S4ADDQ R0, R1, R2 => 00000000 80000003折り返しの問題はインデックス・モード・アドレッシングに限りません。 次の例を考えます。
MOVAB offset(R1), R0シンボル・オフセットがコンパイル時定数でない場合,この命令によって, 値はリンケージ・セクションから読み込まれ,(ADDL命令を使用して) R1内の値に追加されます。これをADDQに変更すると,値が 32ビットを越える場合に結果が変化する可能性があります。
EVAX_SEXTLは64ビット値の下位32ビットを取り,上位32ビットを符号拡張 (値のビット31の内容)で埋め,64ビットの結果をデスティネーションに書き込みます。
次の例は,すべて正しい使用例です。
evax_sextl r1,r2 evax_sextl r1,(r2) evax_sextl (r2), (r3)[r4]これらの例に示すように,オペランドは必ずしもレジスタでなくても構いません。
新規マクロ$IS_32BITSを使用すると, 64ビット値の下位 32ビットの符合拡張をチェックすることができます。詳細は 付録 Bを参照してください。
64Kバイトを越える転送については,OTS$MOVE3およびOTS$MOVE5を使用します。 OTS$MOVE3およびOTS$MOVE5は,ロングワード・サイズ長を受け取ります (LIB$MOVC3およびLIB$MOVC5は,MOVC3およびMOVC5と同じ 64Kバイト長の制限を受けます)。次の例では,MOVC3をOTS$MOVE3で置換します。
MOVC3を使用するコード
MOVC3 BUF$W_LENGTH(R5), (R6), OUTPUT(R7) ; Old code, word lengthロングワード長を伴う同じ内容の64ビット・コード
$SETUP_CALL64 3 ; Specify three arguments in call EVAX_ADDQ R7, #OUTPUT, R7 $PUSH_ARG64 R7 ; Push destination, arg #3 $PUSH_ARG64 R6 ; Push source, arg #2 MOVL BUF$L_LENGTH(R5), R16 $PUSH_ARG64 R16 ; Push length, arg #1 $CALL64 OTS$MOVE3 MOVL BUF$L_LENGTH(R5), R16 EVAX_ADDQ R6, R16, R1 ; MOVC3 returns address past source EVAX_ADDQ R7, R16, R3 ; MOVC3 returns address past destinationMOVC3はR0,R2,R4およびR5をクリアするので, その内容がもはや必要ないことを確認してください。
OTS$MOVE3およびOTS$MOVE5は,『OpenVMS RTL General Purpose (OTS$) Manual』 の中でほかのLIBOTSルーチンと共に説明されています。
最新バージョンのコンパイラを使用する場合, 64ビット・アドレッシング機能を使用しているかどうかに関わらず, 最新バージョンのALPHA$LIBRARY:STARLET.MLBも使用しなければなりません。 システム上に最新バージョンがインストールされ, 論理名が正しいディレクトリを示していることを確認してください。