● 低水準操作

FPU 環境の保護

FPU を直接制御するプログラムでは、FPU 操作中に関数を使用すると、処理内容に干渉する事があります。主処理以外で、FPU 環境に干渉する可能性がある処理を実行する場合は、floatex_fpusavefloatex_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 命令を直に使用して環境の保護を行う事もできます。