この章では,アプリケーション内の条件処理コードに対して,VAXアーキテクチャと Alphaアーキテクチャの違いがどのような影響を与えるかについて説明します。
ほとんどの場合,アプリケーションの条件処理コードは Alphaシステムでも正しく機能します。特に,FORTRANのENDやERR,IOSTAT指定子など, アプリケーション開発において, 高級言語で提供される条件処理機能を使用している場合には,問題はありません。 これらの言語機能はアーキテクチャ固有の条件処理機能からアプリケーションを分離します。
しかし,Alpha条件処理機能とそれに対応する VAX条件処理機能の間にはいくつかの違いがあり, 場合によってはソース・コードを変更しなければなりません。次の場合には, ソース・コードの変更が必要です。
この後の節では,これらの変更について詳しく説明し, ソース・コードの変更が必要かどうかを判断するのに役立つガイドラインも示します。
OpenVMS Alphaの実行時ライブラリ(RTL)にはLIB$ESTABLISHルーチンがありませんが, OpenVMS VAXのRTLにはこのルーチンがあります。OpenVMS Alphaの呼び出し規則により, 条件ハンドラの設定はコンパイラによって行われます。
条件ハンドラを動的に設定しなければならないプログラムのために,一部の Alpha言語では,LIB$ESTABLISHの呼び出しが特別な方法で取り扱われ,実際に RTLルーチンを呼び出さずに適切なコードを生成します。次の言語は,対応する VAX言語と互換性のある方法でLIB$ESTABLISHをサポートします。
OpenVMS Alphaシステム用のDEC CとDEC C++は, LIB$ESTABLISHを組み込み関数として取り扱いますが,OpenVMS VAXまたは OpenVMS AlphaシステムでLIB$ESTABLISHを使用することは望ましくありません。 CおよびC++のプログラマは,LIB$ESTABLISHの代わりに VAXC$ESTABLISHを呼び出すようにしてください(VAXC$ESTABLISHは, OpenVMS Alphaシステム用のDEC CとDEC C++で提供される組み込み関数です)。
Digital Fortranでは,LIB$ESTABLISHおよび LIB$REVERT内部関数に対する宣言が可能であり,これらを Digital Fortran RTL固有のエントリ・ポイントに変換します。
DEC Pascalでは,ESTABLISHとREVERTという組み込みルーチンが提供され, LIB$ESTABLISHおよびLIB$REVERTの代わりに使用できます。 LIB$ESTABLISHを宣言して使用しようとすると,コンパイル時に警告が出されます。
MACRO-32コンパイラは, LIB$ESTABLISHの呼び出しがソース・コードに指定されている場合, これを呼び出そうとします。
MACRO-32プログラムが0(FP)のルーチン・アドレスを格納することにより, 動的ハンドラを設定する場合には,これらのプログラムは, OpenVMS Alphaシステムでコンパイルした場合も正しく動作します。しかし, CALL_ENTRYルーチンの内部からでなければ,JSB (Jump to Subroutine)ルーチンの内部から条件ハンドラ・アドレスを設定することはできません。
ユーザ作成条件処理ルーチンの呼び出しシーケンスは,Alphaシステムでも VAXシステムのときと同じです。条件処理ルーチンは, 例外条件を通知するときにシステムが戻すデータをアクセスするために 2つの引数を宣言します。システムはシグナル・アレイとメカニズム・アレイという 2つの配列を使用して,どの例外条件がシグナルを起動したかを識別する情報を伝達し, 例外が発生したときのプロセッサの状態を報告します。
シグナル・アレイとメカニズム・アレイの形式はシステムで定義され, 『OpenVMS Programming Concepts Manual』に説明されています。Alphaシステムでは, シグナル・アレイに戻されるデータとその形式はVAXシステムの場合と同じです。 図 8-1を参照してください。
次の表はシグナル・アレイ内の各引数を示しています。
引数 | 説明 |
---|---|
引数の数 | AlphaシステムでもVAXシステムでも, この引数には正の整数が格納され,配列内でこの後に続くロングワードの数を示す。 |
状態コード | AlphaシステムでもVAXシステムでも, この引数は32ビットのコードであり, ハードウェアまたはソフトウェア例外条件を一意に識別する。条件コードの形式は Alphaシステムでも変更されておらず, 『OpenVMS Programming Interfaces: Calling a System Routine』 に説明されているとおりである。しかし,Alphaシステムは VAXシステムで戻されるすべての条件コードをサポートするわけではなく, さらにVAXシステムでは戻されない条件コードを定義している。 Alphaシステムで戻すことができないVAX条件コードについては 第8.4節を参照。 |
オプション・メッセージ・ シーケンス |
これらの引数は戻される例外に関する追加情報を提供し, これは各例外に応じて異なる。VAX例外に対するこれらの引数については, 『OpenVMS Programming Concepts Manual』を参照。 |
プログラム・カウンタ (PC) |
例外がトラップである場合には, 例外が発生したときに次に実行される命令のアドレス。例外がフォルトの場合には, 例外の原因となった命令のアドレス。Alphaシステムでは,この引数にはPCの下位 32ビットが格納される(Alphaシステムでは,PCは64ビットの長さである)。 |
プロセッサ・ステータス・ ロングワード(PSL) |
フォーマッティングした32ビットの引数であり, 例外が発生したときのプロセッサの状態を記述する。Alphaシステムでは, この引数にはAlphaの64ビットのプロセッサ・ステータス(PS)・クォドワードの下位 32ビットが格納される。 |
Alphaシステムでは,メカニズム・アレイにはVAXの場合と同様のデータが戻されます。 しかし,その形式は異なります。Alphaシステムで戻されるメカニズム・アレイには, 浮動小数点スクラッチ・レジスタだけでなく, 整数スクラッチ・レジスタの内容も保存されます。さらに,Alphaのレジスタは 64ビットの長さであるため,メカニズム・アレイは,VAXシステムのようにロングワード (32ビット)ではなく,クォドワード(64ビット)で構成されます。 図 8-2はVAXシステムと Alphaシステムでのメカニズム・アレイの形式を比較しています。
次の表はメカニズム・アレイ内の各引数を示しています。
引数 | 説明 |
---|---|
引数の数 | VAXシステムでは, この引数には正の整数が格納され,配列内でその後に続くロングワードの数を示す。 Alphaシステムでは,この引数はメカニズム・アレイ内のクォドワードの数を示し, 引数カウント・クォドワードの数(Alphaシステムでは常に43)を示すわけではない。 |
フラグ | Alphaシステムでは, この引数には追加情報を伝達するためのさまざまなフラグが格納される。たとえば, ビット0がセットされている場合には,プロセスがすでに浮動小数点演算を実行し, 配列内の浮動小数点レジスタが正しいことを示す( VAXシステムのメカニズム・アレイにはこれに対応する引数はない)。 |
フレーム・ポインタ(FP) | VAXシステムでもAlphaシステムでも, この引数には条件ハンドラを設定したスタックの呼び出しフレームのアドレスが格納される。 |
深さ | VAXシステムでもAlphaシステムでも,この引数には, 例外を発生させたフレームを基準にして, 条件処理ルーチンを設定したプロシージャのフレーム番号を表現する整数が格納される。 |
リザーブ | 予約されている。 |
ハンドラ・データ・アドレス | Alphaシステムでは,この引数には, ハンドラが存在する場合はハンドラ・データ・クォドワードのアドレスが格納される (VAXシステムのメカニズム・アレイにはこれに対応する引数はない)。 |
例外スタック・フレーム・アドレス | Alphaシステムでは, この引数には例外スタック・フレームのアドレスが格納される (VAXシステムのメカニズム・アレイにはこれに対応する引数はない)。 |
シグナル・アレイのアドレス | Alphaシステムでは,この引数にはシグナル・アレイのアドレスが格納される (VAXシステムのメカニズム・アレイにはこれに対応する引数はない)。 |
レジスタ | VAXシステムでもAlphaシステムでも, メカニズム・アレイにはスクラッチ・レジスタの内容が格納される。 Alphaシステムでは,この引数にはるかに大きなレジスタ・セットが格納され, 対応する浮動小数点レジスタも格納される。 |
32ビット・シグナル・アレイはAlphaシステムとVAXシステムとで同じであるため, 条件処理ルーチンのソース・コードを変更する必要はないでしょう。しかし, メカニズム・アレイは変更されているため, ソース・コードを変更しなければならないかもしれません。特に, 次のことを確認してください。
SYS$UNWINDシステム・サービスに対してdepth引数のアドレスを指定することにより, 例外処理ハンドラを設定したフレームまで巻き戻すアプリケーションや, SYS$UNWINDシステム・サービスの省略時のdepth引数を使用することにより, 例外処理ハンドラを設定したフレームの呼び出し側まで巻き戻すアプリケーションは, 今後も正しく動作します。depthを負の値として指定した場合には, 例外ベクタを示します(VAXシステムの場合と同じ)。
例 8-1はCで作成した条件処理ルーチンを示しています。
#include <ssdef.h> #include <chfdef.h> . . . 【1】 int cond_handler( sigs, mechs ) struct chf$signal_array *sigs; struct chf$mech_array *mechs; { int status; 【2】 status = LIB$MATCH_COND(sigs->chf$l_sig_name, /* returned code */ SS$_INTOVF); /* test against */ 【3】 if(status != 0) { /* ...Condition matched. Perform processing. */ return SS$_CONTINUE; } else { /* ...Condition does not match. Resignal exception. */ return SS$_RESIGNAL; } }次のリストの各項目は 例 8-1に示した番号に対応しています。
【1】 | このルーチンは, システムがシグナル・アレイとメカニズム・アレイに戻すデータをアクセスするために, sigsとmechsという2つの引数を定義します。このルーチンは前もって定義されている 2つのデータ構造を使用して,引数を宣言します。2つのデータ構造とは chf$signal_arrayとchf$mech_arrayであり,システムによって CHFDEF.Hヘッダ・ファイルに定義されています。 |
【2】 | この条件処理ルーチンは LIB$MATCH_CONDランタイム・ライブラリ・ルーチンを使用することにより, 戻された条件コードと,整数オーバーフローを識別する条件コード (SSDEF.Hに定義されているコード)を比較します。 条件コードはシステム定義のシグナル・データ構造のフィールドとして参照されます (CHFDEF.Hに定義されています)。 |
【3】 | LIB$MATCH_CONDルーチンは, 一致する条件コードを検出したときにゼロ以外の結果を戻します。 条件処理ルーチンはこの結果をもとに,異なるコード・パスを実行します。 |
アプリケーションの条件処理ルーチンは, シグナル・アレイに戻された条件コードを確認することにより, どの例外が通知されているかを識別します。次のプログラムの一文は 例 8-1から抜粋したものであり, 条件処理ルーチンがランタイム・ライブラリ・ルーチン LIB$MATCH_CONDを使用することにより, この作業をどのような方法で実現できるかを示しています。
status = LIB$MATCH_COND( sigs->chf$l_sig_name, /* returned code */ SS$_INTOVF); /* test against */このメカニズムはAlphaシステムでも変更されていません。 32ビットの条件コードの形式とシグナル・アレイ内での位置は, VAXシステムの場合と同じです。しかし,条件処理ルーチンが VAXシステムで受け取っていた条件コードは Alphaシステムでは意味がないでしょう。アーキテクチャが異なるため, VAXシステムで戻されていた一部の例外条件は,Alphaシステムではサポートされません。
ソフトウェア例外の場合には,Alphaシステムは VAXシステムの場合と同じ例外をサポートします。このことについては, オンライン・ヘルプ・メッセージ・ユーティリティまたは 『OpenVMS system messages documentation』に示されています。しかし, ハードウェア例外はソフトウェア例外よりアーキテクチャに依存する部分が多く, 特に算術演算例外はアーキテクチャに依存しています。 VAXシステムでサポートされていたハードウェア例外の一部( 『OpenVMS Programming Concepts Manual』を参照)だけが Alphaシステムでもサポートされます。さらに,Alphaアーキテクチャでは, VAXアーキテクチャでサポートされないいくつかの追加された例外を定義しています。
表 8-1は,Alphaシステムでサポートされない VAXハードウェア例外と,VAXシステムでサポートされない Alphaハードウェア例外を示しています。アプリケーションの例外処理ルーチンがこれらの VAX固有の例外をテストする場合には,対応する Alpha例外をテストするためのコードを追加する必要があります( Alphaシステムでの算術演算例外のテストについての詳しい説明は, 第8.4.1項を参照してください)。
- 注意
- Alphaシステムで実行されるトランスレートされたVAXイメージは,これらの VAX例外を戻すことができます。
VAXシステムでは,アーキテクチャは算術演算例外が同期的に報告されるようにします。 つまり,例外(オーバーフローなど)の原因となったVAX算術演算命令は, ただちに例外処理ハンドラを開始し,後続の命令は実行されません。 例外ハンドラに報告されるプログラム・カウンタ(PC)は, 例外の原因となった算術演算命令のPCです。このため, アプリケーション・プログラムは,たとえば,メイン・シーケンスを再開し, 例外の原因となった操作を同等の操作または別の操作によってエミュレートするか, 置換することができます。
Alphaシステムでは,算術演算例外は非同期的に報告されます。つまり, アーキテクチャの実現方法により,例外の原因となった命令より後の多くの命令 (分岐やジャンプも含む)を実行できます。これらの命令は, 例外の原因となった命令が使用していたオペランドの上に重ね書きする可能性があるため, 例外を解釈したり,修正するのに必要な情報が失われてしまいます。 例外ハンドラに報告されるPCは,例外の原因となった命令のPCではなく, その後に実行された命令のPCです。 例外がアプリケーションの例外ハンドラに報告される時点では, ハンドラは入力データを修正しており, 命令を再起動することができない可能性があります。
このように,算術演算例外の報告方法が基本的に異なるため,Alphaシステムでは, SS$_HPARITHという1つの条件コードを定義し, これによってすべての算術演算例外を示します。たとえば, 整数オーバーフロー例外が発生したときに処理を実行する条件処理ルーチンがアプリケーションに含まれている場合, VAXシステムでは,SS$_INTOVR条件コードが例外処理ルーチンに渡されます。 Alphaシステムでは,この例外はSS$_HPARITHという条件コードによって示されます。 このため,アプリケーションの条件処理ルーチンは, Alpha算術演算例外を対応するVAX例外と誤って解釈することがありません。 処理を行うアプリケーションが,アーキテクチャ固有である可能性があるため, このことは重要です。
図 8-3は SS$_HPARITH例外シグナル・アレイの形式を示しています。
このシグナル・アレイには,SS$_HPARITH例外の固有の3つの引数が格納されます。 それは整数レジスタ・ライト・マスク,浮動小数点レジスタ・ライト・マスク, および例外サマリです。整数および浮動小数点レジスタ・ライト・マスクは, 例外サマリのビットをセットした命令のターゲットであったレジスタを示します。 マスク内の各ビットはレジスタを表現します。例外サマリは最初の 7ビットにフラグをセットすることにより,通知される例外のタイプ( 1つ以上)を示します。表 8-2 はこれらの各ビットがセットされているときの意味を示しています。
ビット | 意味 |
---|---|
0 | ソフトウェアは正常終了した。 |
1 | 浮動小数点演算,変換,または比較操作に誤りがある。 |
2 | 浮動小数点除算で0による除算を実行しようとした。 0による整数除算は報告されないので注意しなければならない。 |
3 | 浮動小数点演算または変換操作で宛先の指数部がオーバーフローした。 |
4 | 浮動小数点演算または変換操作で宛先の指数部がアンダーフローした。 |
5 | 浮動小数点演算または変換操作で正確な算術演算結果と異なる結果が報告された。 |
6 | 浮動小数点数値から整数への変換操作または整数算術演算で宛先の精度がオーバーフローした。 |
算術演算例外に応答して処理を実行する条件処理ルーチンを Alphaシステムで実行するために変更しなければならないかどうかを判断する場合には, 次のガイドラインに従ってください。
ただし,これらの命令を指定すると,性能が低下する可能性があります。 例外の正確な報告がアプリケーションの一部の操作でのみ必要な場合は, そのような操作を含んでいる部分のコンパイルだけにこのオプションを使用するようにしてください。 詳細については,使用するコンパイラのマニュアルを参照してください。
- 注意
- Alphaシステムで実行されるトランスレートされたVAXイメージは, 算術演算例外条件も含めて,VAX例外条件を戻します。
Alphaシステムでは,アラインされていないアドレスをオペランドとして受け付ける Alpha命令(LDQ_U)を使わずに, 自然なアラインメントになっていないアドレスを使用して, レジスタとの間でロングワードまたはクォドワードをロード/ストアしようとする操作を実行すると, データ・アラインメント・トラップが発生します (データ・アラインメントについての詳しい説明は, 第7章を参照してください)。
Alphaシステムのコンパイラは通常,次の操作を実行することにより, アラインメント・フォルトの発生を防止します。
しかし,動的に定義されるデータをコンパイラがアラインすることはできません。 したがってこのような場合は,アラインメント・フォルトが発生する可能性があります。
アラインメント例外は条件コードSS$_ALIGNによって示されます。 図 8-4は, SS$_ALIGN例外によって戻されるシグナル・アレイの要素を示しています。
このシグナル・アレイには,SS$_ALIGN例外固有の2つの引数が格納されます。 それは仮想アドレスとレジスタ番号です。仮想アドレスには, アクセスしているアラインされていないデータのアドレスが格納されます。 レジスタ番号は操作の対象となるレジスタを示します。
いままでに述べてきた条件処理ルーチンの問題に加えて, 条件処理を含むアプリケーションは, システムに対して条件処理ルーチンを設定するなどの他の操作を実行しなければなりません。 ランタイム・ライブラリには, アプリケーションでこれらの操作を実行するためのルーチンが準備されています。 たとえば,アプリケーションでランタイム・ライブラリ・ルーチン LIB$ESTABLISHを呼び出すことにより, 例外が通知されるときに実行される条件処理ルーチンを識別(または設定)できます。
VAXアーキテクチャとAlphaアーキテクチャには相違点があり, 両方のアーキテクチャの呼び出し規則にも違いがあるため, これらの多くの操作の実現方法は同じではありません。 表 8-3は VAXシステムで提供されるランタイム・ライブラリ条件処理サポート・ルーチンと, Alphaシステムではどのルーチンがサポートされるかを示しています。
次のリストは, ランタイム・ライブラリ・ルーチンを使用するアプリケーションにおけるガイドラインを示しています。
省略時の設定により通知されないように設定されている例外は, コンパイル時に通知されるように設定しなければなりません。
たとえば,例 8-2に示したプログラムは FORTRANで作成されており,条件コードSS$_INTOVFを指定することにより, 整数オーバーフローをテストする条件処理ルーチンを指定するために, RTLルーチンLIB$ESTABLISHを使用しています。VAXシステムでは, 整数オーバーフローの検出を可能にするために,プログラムをコンパイルするときに /CHECK=OVERFLOW修飾子を指定しなければなりません。
このプログラムをAlphaシステムで実行するには,条件コードをSS$_INTOVFから SS$_HPARITHに変更しなければなりません (オーバーフローのタイプはシグナル・アレイ内の例外サマリ引数を調べることにより判断できます。 詳しくはコンパイラに関する解説書を参照してください)。VAXシステムの場合と同様に, オーバーフロー検出を可能にするためにはコンパイル・コマンド・ラインに /CHECK=OVERFLOW修飾子を指定なければなりません。DEC Fortranは LIB$ESTABLISHルーチンを組み込み関数として受け付けるため, このルーチンの呼び出しを削除する必要はありません。
C This program types a maximum value of integers C Compile with /CHECK=OVERFLOW and the /EXTEND_SOURCE qualifiers INTEGER*4 int4 EXTERNAL HANDLER CALL LIB$ESTABLISH (HANDLER) 【1】 int4=2147483645 WRITE (6,*) ' Beginning DO LOOP, adding 1 to ', int4 DO I=1,10 int4=int4+1 WRITE (6,*) ' INT*4 NUMBER IS ', int4 END DO WRITE (6,*) ' The end ...' END C This is the condition-handling routine INTEGER*4 FUNCTION HANDLER (SIGARGS, MECHARGS) INTEGER*4 SIGARGS(*),MECHARGS(*) INCLUDE '($FORDEF)' INCLUDE '($SSDEF)' INTEGER INDEX INTEGER LIB$MATCH_COND INDEX = LIB$MATCH_COND (SIGARGS(2), SS$_INTOVF) 【2】 IF (INDEX .EQ. 0 ) THEN HANDLER = SS$_RESIGNAL ELSE IF (INDEX .GT. 0) THEN WRITE (6,*) 'Arithmetic exception detected...' CALL LIB$STOP(SIGARGS(1)) END IF END次のリストの各項目は 例 8-2に示されている番号に対応しています。
【1】 | この例では,条件処理ルーチンを指定するためにLIB$ESTABLISHを呼び出します。 |
【2】 | Alphaシステムでは,条件コードをSS$_INTOVFから SS$_HPARITHに変更しなければなりません。条件処理ルーチンは LIB$STOPルーチンを呼び出すことにより,プログラムの実行を終了します。 |
$ FORTRAN/EXTEND_SOURCE/CHECK=OVERFLOW HANDLER_EX.FOR $ LINK HANDLER_EX $ RUN HANDLER_EX Beginning DO LOOP, adding 1 to 2147483645 INT*4 NUMBER IS 2147483646 INT*4 NUMBER IS 2147483647 Arithmetic exception detected... %TRACE-F-TRACEBACK, symbolic stack dump follows Image Name Module Name Routine Name Line Number rel PC abs PC INT_OVR_HAND INT_OVR_HANDLER HANDLER 1637 00000238 00020238 DEC$FORRTL 0 000651E4 001991E4 ----- above condition handler called with exception 00000504: %SYSTEM-F-HPARITH, high performance arithmetic trap, Imask=00000001, Fmask=00000 000, summary=40, PC=000200E0, PS=0000001B -SYSTEM-F-INTOVF, arithmetic trap, integer overflow at PC=000200E0, PS=0000001B ----- end of exception message 0 84FE9FFC 84FE9FFC INT_OVR_HAND INT_OVR_HANDLER INT_OVR_HANDLER 15 000000E0 000200E0 0 84EFD918 84EFD918 0 7FF23EE0 7FF23EE0