Annotation of nono/fpe/host.c, revision 1.1.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.