OpenVMS Alpha
オペレーティング・システム
64 ビット・アドレッシングおよび
VLM 機能説明書


前へ 次へ 目次 索引


11.4.4 32 ビット・ポインタに制限されている関数

DEC C RTL には 64 ビット・ポインタをサポートしない関数もあります。64 ビット・ポインタをサポートしない関数に 64 ビット・ポインタを渡そうとすると,コンパイラは %CC-W-MAYLOSEDATA 警告メッセージを生成します。/POINTER_SIZE=64 修飾子を指定してコンパイルしたアプリケーションは,64 ビット・ポインタをサポートしない関数に 64 ビット・ポインタを渡すことがないように,ソース・コードの修正が必要な場合があります。

32 ビット・ポインタしか使用できない関数を 表 11-2 に示します。DEC C RTL は,これらの関数に対して 64 ビット・サポートを提供していません。

表 11-2 32 ビット・ポインタに制限されている関数
atexit getopt modf setstate
execve iconv recvmsg setvbuf
execvp initstate sendmsg  
frexp ioctl setbuf  

関数呼び出し処理の一部として,ユーザが提供する関数へのコールバックを行う関数の一覧を 表 11-3 に示します。コールバック・プロシージャに 64 ビット・ポインタが渡されることはありません。

表 11-3 32 ビット・ポインタだけを渡すコールバック
from_vms to_vms
ftw tputs

11.5 ヘッダ・ファイルの読み込み

この節では,DEC C RTL ヘッダ・ファイルで使用されるポインタ・サイズ操作について説明します次の例を参考にヘッダ・ファイルを読み,必要に応じてヘッダ・ファイルを修正してください。

#1

: 
#if INITIAL__POINTER_SIZE (1)
#   if (VMS__VER < 70000000) || !defined __ALPHA (2)
#      error " Pointer size usage not permitted before OpenVMS Alpha V7.0" 
#   endif 
#   pragma __pointer_size __save (3)
#   pragma __pointer_size 32 (4)
#endif 
: 
: 
#if __INITIAL_POINTER__SIZE (5)
#   pragma __pointer_size 64 
#endif 
: 
: 
#if __INITIAL_POINTER_SIZE (6)
#   pragma __pointer_size __restore 
#endif 
: 
 
 

/POINTER_SIZE 修飾子をサポートするすべての DEC C コンパイラは,あらかじめマクロ__INITIAL_POINTER_SIZEを定義しています。このマクロが定義されていない場合,DEC C RTL ヘッダ・ファイルは,暗黙値 0 を使用するという ANSI 規則を利用します。

/POINTER_SIZE 修飾子が使用される場合,マクロは 32 または 64 として定義されます。この修飾子が使用されない場合は,0 として定義されます。(1) の文は,"ユーザがコマンド・ラインで /POINTER_SIZE=32 または /POINTER_SIZE=64 を指定した場合" という意味です。

DEC C バージョン 5.2 以降は,多くの OpenVMS プラットフォームでサポートされます。コンパイルのターゲットが 64 ビット・ポインタをサポートしない場合,(2) の行はエラー・メッセージを生成します。

ヘッダ・ファイルは,このヘッダがインクルードされる時点では,作用する実際のポインタ・サイズ・コンテキストを決定することができません。さらに,DEC C コンパイラは,__INITIAL_POINTER_SIZEマクロと,ポインタ・サイズを変更するメカニズムだけを提供し,現在のポインタ・サイズを決定することはしません。

ポインタ・サイズに依存するヘッダ・ファイルはすべて,ポインタ・サイズ・コンテキストの保存 (3),初期化 (4),変更 (5),および復元 (6) を行う必要があります。

#2

: 
#ifndef __CHAR_PTR32 (1)
#   define __CHAR_PTR32 1 
    typedef char * __char_ptr32; 
    typedef const char * __const_char_ptr32; 
#endif 
: 
: 
#if __INITIAL_POINTER__SIZE 
#   pragma __pointer_size 64 
#endif 
: 
: 
#ifndef __CHAR_PTR64 (2)
#   define __CHAR_PTR64 1 
    typedef char *__ char_ptr64; 
    typedef const char * __const_char_ptr64; 
#endif 
: 
 
 

64 ビット・ポインタ・サイズ・コンテキストの中で,32 ビット・ポインタを参照する必要がある関数プロトタイプがあります。また,32 ビット・ポインタ・サイズ・コンテキストの中で,64 ビット・ポインタを参照する必要がある関数プロトタイプもあります。

DEC C コンパイラは,typedefが作成される時点で,typedefで使用されるポインタ・サイズを結合させます。__char_ptr32typedef宣言(1) は 32 ビット・コンテキストで行われます。__char_ptr64typedef宣言(2) は 64 ビット・コンテキストで行われます。

#3

: 
#if INITIAL__POINTER_SIZE 
#   if (__VMS_VER < 70000000) || !defined __ALPHA 
#      error " Pointer size usage not permitted before OpenVMS Alpha V7.0" 
#   endif 
#   pragma __pointer_size save 
#   pragma __pointer_size 32 
#endif 
: 
(1)
: 
#if __INITIAL_POINTER_SIZE (2)
#   pragma __pointer_size 64 
#endif 
: 
(3)
: 
int abs (int __j); (4)
: 
__char_ptr32 strerror (int __errnum); (5)
: 
 
 

64 ビット・ポインタをサポートする関数プロトタイプの宣言の前に,ポインタ・コンテキストが 32 ビット・ポインタから 64 ビット・ポインタに変更されています (2)

32 ビット・ポインタに制限されている関数は,ヘッダ・ファイルの 32 ビット・ポインタ・コンテキスト・セクション (1) に配置されています。ほかの関数はすべて,ヘッダ・ファイルの 64 ビット・ポインタ・コンテキスト・セクション (3) に配置されています。

ポインタ・サイズの影響を受けない関数 ((4) および (5)) は,64 ビット・セクションに配置されています。これらの関数は 32 ビット・アドレスの戻り値を除き,ポインタ・サイズの影響は受けません(5)。またこれらの関数は 64 ビット・セクションにあり,前述の 32 ビット固有のtypedefを使用します。

#4

: 
#if __INITIAL_POINTER_SIZE 
#   pragma __pointer_size 64 
#endif 
: 
: 
#if __INITIAL_POINTER_SIZE == 32 (1)
#   pragma __pointer_size 32 
#endif 
: 
char *strcat (char *__s1, __const_char_ptr64 __s2); (2)
: 
#if __INITIAL_POINTER_SIZE 
#   pragma __pointer_size 32 
    : 
    char *_strcat32  (char *__s1, __const_char_ptr64 __s2); (3)
    : 
#   pragma __pointer_size 64 
    : 
    char *_strcat64  (char *__s1, const char *__s2); (4)
    : 
#endif 
: 
 
 

この例は,32 ビット実装と 64 ビット実装の両方を持つ関数に対する宣言です。これらの宣言は,ヘッダ・ファイルの 64 ビット・セクションに配置されています。

関数の通常の宣言 (2) は,/POINTER_SIZE 修飾子で指定したポインタ・サイズを使用して行われます。ヘッダ・ファイルが 64 ビット・ポインタ・コンテキストにあり,(1) に文を指定しているため,(2) の宣言は /POINTER_SIZE 修飾子と同じポインタ・サイズ・コンテキストを使用して行われます。

32 ビット固有のインタフェース (3) および 64 ビット固有のインタフェース (4) は,32 ビット・ポインタ・サイズ・コンテキストおよび 64 ビット・ポインタ・サイズ・コンテキストの中でそれぞれ宣言されています。


第 12 章
MACRO--32 プログラミングの 64 ビット・アドレッシング・サポート

本章では,MACRO--32 コンパイラおよび関連コンポーネントによる 64 ビット・アドレッシング・サポートについて説明します。主に引数の受け渡しとアドレス計算に対して変更が行われています。

12.1 64 ビット・アドレッシングのガイドライン

OpenVMS Alpha 用にコンパイルされる VAX MACRO コード内での,64 ビット・アドレッシングの使用に関するガイドラインを次に示します。

12.2 64 ビット・アドレッシングのための新規コンポーネントおよび変更されたコンポーネント

MACRO-32 プログラミングでの 64 ビット・アドレッシング・サポートを提供する,新規コンポーネントおよび変更されたコンポーネントの一覧を 表 12-1 に示します。

表 12-1 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 マクロ

12.3 64 ビット値の引き渡し

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

12.3.1 固定長サイズ引数リストでの呼び出し

固定サイズ・リストでの呼び出しの場合, 表 12-2 の手順に従って新規マクロを使用します。

表 12-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 を使用する前に必要です。引数の個数が 6 個を越える場合,このマクロはローカル JSB ルーチンを作成し,これが起動されて呼び出しを実行します。引数の個数が 6 個以下の場合,引数のロードと呼び出しはインラインで行われ,きわめて効率的です。なお,$SETUP_CALL64 に指定される引数の個数には,# が含まれないことに注意してください。(これは,標準呼び出しシーケンスが,オクタワード・アライン・スタックの先頭のスタック引数の,オクタワード・アラインを求めるためです。JSB ルーチンは,このアライン操作を行います。)

インライン・オプションを使用すると,ローカル JSB ルーチンがなくても,6 個を越える引数を指定して呼び出しを強制的に実行できます。ただし,その使用には制限があります (詳細は 付録 B を参照してください)。

$PUSH_ARG64 マクロは,引数を正しい引数レジスタやスタック位置に直接移動します。これは実際にはスタック・プッシュではありませんが,32 ビット呼び出しの中で使用される PUSHL 命令に似ています。

$CALL64 マクロは引数カウント・レジスタを設定し,ターゲット・ルーチンを起動します。JSB ルーチンが作成された場合は,そのルーチンを終了させます。プッシュされた引数の個数が,$SETUP_CALL64 で指定された個数に一致しない場合,エラーが報告されます。$CALL64 および $PUSH_ARG64 を使用する前に,$SETUP_CALL64 が起動されていることを確認してください。

12.3.1.1 $SETUP_CALL64,$PUSH_ARG64,および $CALL64 の使用上の注意

$SETUP_CALL64,$PUSH_ARG64,$CALL64 を使用するときは,次の点に注意してください。

注意

$SETUP_CALL64,$PUSH_ARG64,および $CALL64 マクロは,インライン・シーケンスで使用することを目的としています。つまり,$SETUP_CALL64/$PUSH_ARG64/$CALL64 シーケンスの中央に分岐したり,$PUSH_ARG64 マクロの回りで分岐することはできず,シーケンスを出て $CALL64 を避けることもできません。

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


前へ 次へ 目次 索引