● 低水準操作
FPU 環境の保護
FPU を直接制御するプログラムでは、FPU 操作中に関数を使用すると、処理内容に干渉する事があります。主処理以外で、FPU 環境に干渉する可能性がある処理を実行する場合は、floatex_fpusave 、floatex_fpuload を使用して FPU 環境を保護してください。
unsigned char fpu_env[128];
floatex_fpusave(fpu_env); /* 環境の保存 */
/*
FPU 環境に影響する処理を
ここに記述します。
*/
floatex_fpuload(fpu_env,0); /* 環境の復元 */
floatex_fpusave 、floatex_fpuload の間で行われた処理は、元の FPU 環境には影響しません。環境を保存しておくメモリをローカルで確保すれば、再帰的な処理を行う時等にも使用する事ができます。
例.レジスタスタック参照関数
#include <stdio.h>
#include "floatex.h"
#define STACKTAG(TAG,I) (((TAG) >> ((I) << 1)) & 3)
/*
タグワードとレジスタスタックの内容を表示する
実行後は、例外フラグがクリアされます。
*/
void print_reg(void)
{
REGSTACK dat;
char buf[32],*p;
int i,c;
unsigned int oldcw;
unsigned char fpu_env[128];
/*
例外ハンドラ内で使用される場合に備えて
例外を保留のままマスクを掛ける
*/
floatex_loadcw2((oldcw = floatex_storecw2()) | FEX_MCW_EM);
floatex_get_regstack(&dat); /* レジスタスタックの取得 */
printf("\n スタックトップ:R%d\n",dat.stacktop);
if (dat.stackfault != 0)
p = (dat.stackfault > 0)? "overflow" : "underflow";
else
p = "normal";
printf("スタックフォルト:%s\n\n",p);
/** タグワードの表示 **/
i = 7;
printf("ST(7):");
do{
c = STACKTAG(dat.tag,i);
printf("%d%d",c >> 1,c & 1);
if (i)
printf(" ");
}while(--i >= 0);
printf(":ST(0)\n");
printf("----------------------------------------------------\n");
/** レジスタスタックの表示 **/
/* floatex_ldstr_ldtoa が FPU を使用するので、FPU の環境を退避 */
floatex_fpusave(fpu_env);
i = 0;
do{
printf("ST(%d) : ",i);
switch(STACKTAG(dat.tag,i)){
case 0: /* 有効 */
case 1: /* ゼロ */
floatex_ldstr_ldtoa(dat.reg[i],buf);
printf("%s\n",buf);
break;
case 2: /* NaN 、∞ 、デノーマル */
printf("特殊\n");
break;
case 3: /* 空のレジスタ */
printf("空\n");
break;
}
}while(++i < 8);
floatex_fpuload(fpu_env,1); /* 保存した環境を復元 */
printf("----------------------------------------------------\n\n");
floatex_loadcw(oldcw); /* 元の設定に戻す */
}
※ マニュアル内のいくつかのプログラム例で、この関数を使用しているものが
あります。コンパイルする場合は、ソースコードにこの関数を追加してくだ
さい。
fsave / fnsave 命令と frstor 命令を直に使用して環境の保護を行う事もできます。
- 命令による退避/復元は、オーバーヘッドが無い分、パフォーマンスに優れます。
アセンブラをメインに使用している場合は、アセンブラコード内から関数を呼び出すより、命令を使用した方が簡単です。
- floatex.dll による退避/復元は、大きなオーバーヘッドがあるためパフォーマンスが良くないのですが、保存してある環境データが変更された場合はロード処理を行わないので、FPU が意図しない状態に変更されてしまう危険性が比較的低めです。