|
|
nono 1.7.0
//
// XM6i
// Copyright (C) 2013 Tetsuya Isaki
//
// for host FPU mode
//
#include <float.h>
#include <stdio.h>
#include <string.h>
#include "cmake_config.h"
#include "fpu_emulate.h"
/*
* M68881/2 の浮動小数点表現(IEEE754)をホストの浮動小数点表現に変換する。
*/
/* ホスト演算用のダミー fpemu */
static struct fpemu dummyfe;
float
fpu_to_host_float(const uint32_t *src)
{
return *(const float *)src;
}
double
fpu_to_host_double(const uint32_t *src)
{
double dst = 0; /* shut up gcc */
uint32_t *d = (uint32_t *)&dst;
d[1] = src[0];
d[0] = src[1];
return dst;
}
#if defined(HAVE_LONG_DOUBLE)
long double
fpu_to_host_ldouble(const uint32_t *src)
{
long double dst = 0; /* shut up gcc */
uint32_t *d = (uint32_t *)&dst;
#if LONG_DOUBLE == 16
/* amd64 だと16バイト境界にしたいのでパディングがあるだけ */
d[3] = 0;
#endif
/* intel フォーマットは16bitパディングの位置が 68881 とは逆 */
d[2] = src[0] >> 16;
d[1] = src[1];
d[0] = src[2];
return dst;
}
#endif /* HAVE_LONG_DOUBLE */
void
host_float_to_fpu(uint32_t *dst, float src)
{
// stub
}
void
host_double_to_fpu(uint32_t *dst, double src)
{
uint32_t *s = (uint32_t *)&src;
dst[1] = s[0];
dst[0] = s[1];
}
void
host_ldouble_to_fpu(uint32_t *dst, long double src)
{
// stub
}
/*
* fpn 表現とホスト浮動小数点の変換
*/
/*
* +-INF を作成して返す。
* 符号部は fp の符号を使うが、指数部/仮数部はこちらで用意する。
* 特に ISINF(fp) で判定した場合 fp の仮数部は不定なので流用してはいけない。
*/
static inline double
fp2dbl_inf(const struct fpn *fp)
{
uint64_t v;
if (fp->fp_sign) {
// -INF
v = 0xfff0000000000000ULL;
} else {
// +INF
v = 0x7ff0000000000000ULL;
}
return *(double*)&v;
}
double
fp2dbl(const struct fpn *fp)
{
int exp;
uint64_t v;
if (ISNAN(fp)) {
exp = DBL_EXP_INFNAN;
} else if (ISINF(fp)) {
return fp2dbl_inf(fp);
} else {
exp = fp->fp_exp + DBL_EXP_BIAS;
// exp <= 0 は X 精度を D 精度にするとアンダーフローするケース。
if (ISZERO(fp) || exp <= 0) {
if (fp->fp_sign) {
return -0.0;
} else {
return 0.0;
}
} else if (exp >= DBL_EXP_INFNAN) {
return fp2dbl_inf(fp);
}
}
v = (fp->fp_sign);
v <<= 11;
v |= exp;
v <<= FP_LG;
// mant の有効な上位の 52 ビットを取り出す
v |= fp->fp_mant[0] & (FP_1 - 1);
v <<= 32;
v |= fp->fp_mant[1];
v <<= 2;
v |= (fp->fp_mant[2] >> (32-2)) & 0x03;
return *(double*)&v;
}
long double
fp2ldbl(const struct fpn *f)
{
struct fpn fp;
uint32_t a[3];
CPYFPN(&fp, f);
fpu_implode(&dummyfe, &fp, FTYPE_EXT, a);
return fpu_to_host_ldouble(a);
}
void
dbl2fp(struct fpn *fp, double src)
{
uint32_t a[2];
host_double_to_fpu(a, src);
fpu_explode(&dummyfe, fp, FTYPE_DBL, a);
return;
}
void
ldbl2fp(struct fpn *fp, long double src)
{
// stub
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.