3.17 ユーザ定義の例外トラップハンドラの記述

ユーザ定義の例外トラップハンドラでは、デフォルトの例外処理動作をオーバーライドすることができます。例えば、Fortran コードを変換する場合は、無効演算例外でなくゼロ除算例外をオーバーライドして 1 が返されるようにしたほうがよい場合もあります。

これらの機能では、--fpmode=ieee_full--fpmode=ieee_fixed など、例外をサポートする浮動小数点モデルを選択する必要があります。
ユーザ定義の例外トラップハンドラをインストールする場合は、そのハンドラを以下のような関数として宣言します。
__softfp __ieee_value_t myhandler(__ieee_value_t op1,                                   __ieee_value_t op2,                                   __ieee_edata_t edata);
この関数からの戻り値は、__ieee_value_t 型で、その例外の原因となった演算の結果として使用されます。
ハンドラとして使用するには、関数を __softfp として宣言する必要があります。
この関数のパラメータは以下のとおりです。
op1op2
このパラメータは、以下のように例外が発生した演算のオペランド、または中間結果を指定します。
  • 無効演算例外とゼロによる除算例外の場合は、元のオペランドが渡されます。
  • 不正確結果例外の場合は、状況にかかわらず返される汎用の結果が渡されます。この結果は op1 で渡されます。
  • オーバーフロー例外の場合は、中間結果が渡されます。この結果は、指数範囲が十分大きい場合にこの演算で返される数値を計算し、その指数を形式に収まるように調整することによって計算されます。この指数は、単精度の場合は 192(0xC0)ずつ、倍精度の場合は 1536(0x600)ずつ調整されます。
    double から float への変換時にオーバーフロー例外が発生した場合、その結果は double 形式で単精度に丸められ、指数部は 192 のバイアスがかけられた数値です。
  • アンダーフロー例外の場合は、同じような中間結果が生成されますが、バイアス値は指数から減算されるのではなく、指数に加算されます。edata パラメータにも、中間結果が「切り上げ」、「切り下げ」、「処理なし」のいずれであるかを示すフラグが保持されます。
__ieee_value_t 型は、オペランドとして渡せるすべての型の共用体として、以下のように定義されています。
typedef union{     float __f;     float __s;     double __d;     short __h;     unsigned short __uh;     int __i;     unsigned int __ui;     long long __l;     unsigned long long __ul;     .../* __STRICT_ANSI__ */     struct { int __word1, __word2; } __str; } __ieee_value_t;             /* トラップに渡される入力値と出力値 */

--strict を指定せずにコンパイルされたプログラムに、フィールドの名前が異なる __ieee_value_t の以前の定義を使用するコードが含まれている場合、その古いコードはそのまま機能します。詳細については、fenv.h ファイルを参照して下さい。
edata
これには、発生した例外と、実行された演算に関する情報を示すフラグが保持されます(__ieee_edata_t 型は unsigned int と同じです)。

例外トラップハンドラの edata フラグ

edata には以下のフラグが保持されます。
edata & FE_EX_RDIR
アンダーフローでの中間結果が切り下げられた場合は、ゼロ以外の値が設定され、切り上げられた場合、または丸めが行われなかった場合はゼロが設定されます(最後の 2 つの違いは、不正確結果ビットで示されます)。このビットは、他のタイプの例外では無意味です。
edata & FE_EX_exception
指定された exceptionINVALIDDIVBYZEROOVERFLOWUNDERFLOW、または INEXACT)が発生した場合は、ゼロ以外の値が設定されます。これを使用すると、以下のことができるようになります。
  • 複数の例外タイプに同じハンドラ関数を使用する(その関数でこれらのビットをテストすることで、処理されるべき例外が識別されます)。
  • オーバーフローとアンダーフローの中間結果が丸められた値だったか、正確な値だったかを判別する。
FE_EX_INEXACT ビットは、 FE_EX_OVERFLOW または FE_EX_UNDERFLOW との組み合わせで設定できるため、不正確かどうかをテストする前にオーバーフローとアンダーフローをテストすることによって、実際に発生した例外のタイプを決定する必要があります。
edata & FE_EX_FLUSHZERO
演算が実行されたときに FZ ビットが設定された場合は、ゼロ以外の値が設定されます。
edata & FE_EX_ROUND_MASK
演算に適用される丸めモードを表します。例外が発生した演算が、必ずゼロに丸められる _ffix などのルーチンであった場合を除き、通常、このモードは現在の丸めモードと同じになります。利用可能な丸めモードの値は、 FE_EX_ROUND_NEARESTFE_EX_ROUND_PLUSINFFE_EX_ROUND_MINUSINF、および FE_EX_ROUND_ZERO です。
edata & FE_EX_INTYPE_MASK
これは、次の表に示すいずれかの値になり、関数のオペランドの型を表します。

表 3-5 FE_EX_INTYPE_MASK オペランドの型フラグ

フラグ オペランドの型
FE_EX_INTYPE_FLOAT float
FE_EX_INTYPE_DOUBLE double
FE_EX_INTYPE_FD float double
FE_EX_INTYPE_DF double float
FE_EX_INTYPE_HALF short
FE_EX_INTYPE_INT int
FE_EX_INTYPE_UINT unsigned int
FE_EX_INTYPE_LONGLONG long long
FE_EX_INTYPE_ULONGLONG 符号なし long long
edata & FE_EX_OUTTYPE_MASK
これは、次の表に示すいずれかの値になり、関数のオペランドの型を表します。

表 3-6 FE_EX_OUTTYPE_MASK オペランドの型フラグ

フラグ オペランドの型
FE_EX_OUTTYPE_FLOAT float
FE_EX_OUTTYPE_DOUBLE double
FE_EX_OUTTYPE_HALF short
FE_EX_OUTTYPE_INT int
FE_EX_OUTTYPE_UINT unsigned int
FE_EX_OUTTYPE_LONGLONG long long
FE_EX_OUTTYPE_ULONGLONG 符号なし long long
edata & FE_EX_FN_MASK
この値は、以下の表に示すいずれかの演算コードになり、例外が発生した演算の性質を表します。

表 3-7 FE_EX_FN_MASK オペランドの演算の型フラグ

フラグ 演算の型
FE_EX_FN_ADD 加算
FE_EX_FN_SUB 減算
FE_EX_FN_MUL 乗算
FE_EX_FN_DIV 除算
FE_EX_FN_REM 剰余
FE_EX_FN_RND 整数への丸め
FE_EX_FN_SQRT 平方根
FE_EX_FN_CMP 比較
FE_EX_FN_CVT 形式変換
FE_EX_FN_LOGB 指数フェッチ
FE_EX_FN_SCALBN
スケール

FE_EX_INTYPE_MASK フラグは、最初のオペランドの型だけを表します。2 番目のオペランドは常に int 型です。
FE_EX_FN_NEXTAFTER
次に表現可能な番号

いずれのオペランドも同じ型です。nexttoward の呼び出しにより、2 番目のオペランドの値が、最初のオペランドと同じ型に変更されます。これは結果には影響しません。
FE_EX_FN_RAISE この例外は、feraiseexcept() または feupdateenv() によって明示的に生成されます。この場合、edata のワードのほぼすべてが無効となります。
演算が比較である場合、その結果は int として返す必要があり、以下の表に示す 4 つの値のいずれかである必要があります。
比較と変換を除くすべての演算において、入力と出力は同じ型です。

表 3-8 FE_EX_CMPRET_MASK の比較型フラグ

フラグ 比較
FE_EX_CMPRET_LESS op1 < op2
FE_EX_CMPRET_EQUAL op1 = op2
FE_EX_CMPRET_GREATER op1 > op2
FE_EX_CMPRET_UNORDERED op1 と op2 の比較不能
関連する概念
3.18 ユーザ定義の例外ハンドラの例
3.19 シグナルによる例外トラップ処理
3.29 IEEE 754 浮動小数点演算で発生する例外
3.8 ARM 浮動小数点環境の制御
関連する参考文書
3.16 C99 インタフェースの ARM 浮動小数点コンパイラ拡張
3.10 ARM 浮動小数点環境を制御するための C99 互換関数
5.5 __ieee_status()
関連情報
--fpmode=model コンパイラオプション
--strict、--no_strict コンパイラオプション
非機密扱いPDF file icon PDF 版ARM DUI0475KJ
Copyright © 2010-2014 ARM.All rights reserved.