Annotation of nono/fpe/host.c, revision 1.1

1.1     ! root        1: //
        !             2: // XM6i
        !             3: // Copyright (C) 2013 [email protected]
        !             4: //
        !             5: // for host FPU mode
        !             6: //
        !             7: 
        !             8: #include <float.h>
        !             9: #include <stdio.h>
        !            10: #include <string.h>
        !            11: 
        !            12: #include "cmake_config.h"
        !            13: #include "fpu_emulate.h"
        !            14: 
        !            15: /*
        !            16:  * M68881/2 の浮動小数点表現(IEEE754)をホストの浮動小数点表現に変換する。
        !            17:  */
        !            18: 
        !            19: /* ホスト演算用のダミー fpemu */
        !            20: static struct fpemu dummyfe;
        !            21: 
        !            22: float
        !            23: fpu_to_host_float(const uint32_t *src)
        !            24: {
        !            25:        return *(const float *)src;
        !            26: }
        !            27: 
        !            28: double
        !            29: fpu_to_host_double(const uint32_t *src)
        !            30: {
        !            31:        double dst = 0; /* shut up gcc */
        !            32:        uint32_t *d = (uint32_t *)&dst;
        !            33: 
        !            34:        d[1] = src[0];
        !            35:        d[0] = src[1];
        !            36:        return dst;
        !            37: }
        !            38: 
        !            39: #if defined(HAVE_LONG_DOUBLE)
        !            40: long double
        !            41: fpu_to_host_ldouble(const uint32_t *src)
        !            42: {
        !            43:        long double dst = 0;    /* shut up gcc */
        !            44:        uint32_t *d = (uint32_t *)&dst;
        !            45: 
        !            46: #if LONG_DOUBLE == 16
        !            47:        /* amd64 だと16バイト境界にしたいのでパディングがあるだけ */
        !            48:        d[3] = 0;
        !            49: #endif
        !            50:        /* intel フォーマットは16bitパディングの位置が 68881 とは逆 */
        !            51:        d[2] = src[0] >> 16;
        !            52:        d[1] = src[1];
        !            53:        d[0] = src[2];
        !            54: 
        !            55:        return dst;
        !            56: }
        !            57: #endif /* HAVE_LONG_DOUBLE */
        !            58: 
        !            59: void
        !            60: host_float_to_fpu(uint32_t *dst, float src)
        !            61: {
        !            62:        // stub
        !            63: }
        !            64: 
        !            65: void
        !            66: host_double_to_fpu(uint32_t *dst, double src)
        !            67: {
        !            68:        uint32_t *s = (uint32_t *)&src;
        !            69: 
        !            70:        dst[1] = s[0];
        !            71:        dst[0] = s[1];
        !            72: }
        !            73: 
        !            74: void
        !            75: host_ldouble_to_fpu(uint32_t *dst, long double src)
        !            76: {
        !            77:        // stub
        !            78: }
        !            79: 
        !            80: /*
        !            81:  * fpn 表現とホスト浮動小数点の変換
        !            82:  */
        !            83: 
        !            84: /*
        !            85:  * +-INF を作成して返す。
        !            86:  * 符号部は fp の符号を使うが、指数部/仮数部はこちらで用意する。
        !            87:  * 特に ISINF(fp) で判定した場合 fp の仮数部は不定なので流用してはいけない。
        !            88:  */
        !            89: static inline double
        !            90: fp2dbl_inf(const struct fpn *fp)
        !            91: {
        !            92:        uint64_t v;
        !            93: 
        !            94:        if (fp->fp_sign) {
        !            95:                // -INF
        !            96:                v = 0xfff0000000000000ULL;
        !            97:        } else {
        !            98:                // +INF
        !            99:                v = 0x7ff0000000000000ULL;
        !           100:        }
        !           101:        return *(double*)&v;
        !           102: }
        !           103: 
        !           104: double
        !           105: fp2dbl(const struct fpn *fp)
        !           106: {
        !           107:        int exp;
        !           108:        uint64_t v;
        !           109: 
        !           110:        if (ISNAN(fp)) {
        !           111:                exp = DBL_EXP_INFNAN;
        !           112:        } else if (ISINF(fp)) {
        !           113:                return fp2dbl_inf(fp);
        !           114:        } else {
        !           115:                exp = fp->fp_exp + DBL_EXP_BIAS;
        !           116:                // exp <= 0 は X 精度を D 精度にするとアンダーフローするケース。
        !           117:                if (ISZERO(fp) || exp <= 0) {
        !           118:                        if (fp->fp_sign) {
        !           119:                                return -0.0;
        !           120:                        } else {
        !           121:                                return 0.0;
        !           122:                        }
        !           123:                } else if (exp >= DBL_EXP_INFNAN) {
        !           124:                        return fp2dbl_inf(fp);
        !           125:                }
        !           126:        }
        !           127: 
        !           128:        v = (fp->fp_sign);
        !           129:        v <<= 11;
        !           130:        v |= exp;
        !           131:        v <<= FP_LG;
        !           132:        // mant の有効な上位の 52 ビットを取り出す
        !           133:        v |= fp->fp_mant[0] & (FP_1 - 1);
        !           134:        v <<= 32;
        !           135:        v |= fp->fp_mant[1];
        !           136:        v <<= 2;
        !           137:        v |= (fp->fp_mant[2] >> (32-2)) & 0x03;
        !           138: 
        !           139:        return *(double*)&v;
        !           140: }
        !           141: 
        !           142: long double
        !           143: fp2ldbl(const struct fpn *f)
        !           144: {
        !           145:        struct fpn fp;
        !           146:        uint32_t a[3];
        !           147: 
        !           148:        CPYFPN(&fp, f);
        !           149:        fpu_implode(&dummyfe, &fp, FTYPE_EXT, a);
        !           150:        return fpu_to_host_ldouble(a);
        !           151: }
        !           152: 
        !           153: void
        !           154: dbl2fp(struct fpn *fp, double src)
        !           155: {
        !           156:        uint32_t a[2];
        !           157: 
        !           158:        host_double_to_fpu(a, src);
        !           159:        fpu_explode(&dummyfe, fp, FTYPE_DBL, a);
        !           160:        return;
        !           161: }
        !           162: 
        !           163: void
        !           164: ldbl2fp(struct fpn *fp, long double src)
        !           165: {
        !           166:        // stub
        !           167: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.