|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.