📄 sim-fpu.c
字号:
/* Let loop determine first value of s (either 1 or 2) */ b = IMPLICIT_1; q = 0; s = 0; while (b) { unsigned64 t = s + b; if (t <= y) { s |= (b << 1); y -= t; q |= b; } y <<= 1; b >>= 1; } ASSERT (q >= IMPLICIT_1 && q < IMPLICIT_2); f->fraction = q; if (y != 0) { f->fraction |= 1; /* stick remaining bits */ return sim_fpu_status_inexact; } else return 0; }}/* int/long <-> sim_fpu */INLINE_SIM_FPU (int)sim_fpu_i32to (sim_fpu *f, signed32 i, sim_fpu_round round){ i2fpu (f, i, 0); return 0;}INLINE_SIM_FPU (int)sim_fpu_u32to (sim_fpu *f, unsigned32 u, sim_fpu_round round){ u2fpu (f, u, 0); return 0;}INLINE_SIM_FPU (int)sim_fpu_i64to (sim_fpu *f, signed64 i, sim_fpu_round round){ i2fpu (f, i, 1); return 0;}INLINE_SIM_FPU (int)sim_fpu_u64to (sim_fpu *f, unsigned64 u, sim_fpu_round round){ u2fpu (f, u, 1); return 0;}INLINE_SIM_FPU (int)sim_fpu_to32i (signed32 *i, const sim_fpu *f, sim_fpu_round round){ signed64 i64; int status = fpu2i (&i64, f, 0, round); *i = i64; return status;}INLINE_SIM_FPU (int)sim_fpu_to32u (unsigned32 *u, const sim_fpu *f, sim_fpu_round round){ unsigned64 u64; int status = fpu2u (&u64, f, 0); *u = u64; return status;}INLINE_SIM_FPU (int)sim_fpu_to64i (signed64 *i, const sim_fpu *f, sim_fpu_round round){ return fpu2i (i, f, 1, round);}INLINE_SIM_FPU (int)sim_fpu_to64u (unsigned64 *u, const sim_fpu *f, sim_fpu_round round){ return fpu2u (u, f, 1);}/* sim_fpu -> host format */#if 0INLINE_SIM_FPU (float)sim_fpu_2f (const sim_fpu *f){ return fval.d;}#endifINLINE_SIM_FPU (double)sim_fpu_2d (const sim_fpu *s){ sim_fpu_map val; if (sim_fpu_is_snan (s)) { /* gag SNaN's */ sim_fpu n = *s; n.class = sim_fpu_class_qnan; val.i = pack_fpu (&n, 1); } else { val.i = pack_fpu (s, 1); } return val.d;}#if 0INLINE_SIM_FPU (void)sim_fpu_f2 (sim_fpu *f, float s){ sim_fpu_map val; val.d = s; unpack_fpu (f, val.i, 1);}#endifINLINE_SIM_FPU (void)sim_fpu_d2 (sim_fpu *f, double d){ sim_fpu_map val; val.d = d; unpack_fpu (f, val.i, 1);}/* General */INLINE_SIM_FPU (int)sim_fpu_is_nan (const sim_fpu *d){ switch (d->class) { case sim_fpu_class_qnan: case sim_fpu_class_snan: return 1; default: return 0; }}INLINE_SIM_FPU (int)sim_fpu_is_qnan (const sim_fpu *d){ switch (d->class) { case sim_fpu_class_qnan: return 1; default: return 0; }}INLINE_SIM_FPU (int)sim_fpu_is_snan (const sim_fpu *d){ switch (d->class) { case sim_fpu_class_snan: return 1; default: return 0; }}INLINE_SIM_FPU (int)sim_fpu_is_zero (const sim_fpu *d){ switch (d->class) { case sim_fpu_class_zero: return 1; default: return 0; }}INLINE_SIM_FPU (int)sim_fpu_is_infinity (const sim_fpu *d){ switch (d->class) { case sim_fpu_class_infinity: return 1; default: return 0; }}INLINE_SIM_FPU (int)sim_fpu_is_number (const sim_fpu *d){ switch (d->class) { case sim_fpu_class_denorm: case sim_fpu_class_number: return 1; default: return 0; }}INLINE_SIM_FPU (int)sim_fpu_is_denorm (const sim_fpu *d){ switch (d->class) { case sim_fpu_class_denorm: return 1; default: return 0; }}INLINE_SIM_FPU (int)sim_fpu_sign (const sim_fpu *d){ return d->sign;}INLINE_SIM_FPU (int)sim_fpu_exp (const sim_fpu *d){ return d->normal_exp;}INLINE_SIM_FPU (unsigned64)sim_fpu_fraction (const sim_fpu *d){ return d->fraction;}INLINE_SIM_FPU (unsigned64)sim_fpu_guard (const sim_fpu *d, int is_double){ unsigned64 rv; unsigned64 guardmask = LSMASK64 (NR_GUARDS - 1, 0); rv = (d->fraction & guardmask) >> NR_PAD; return rv;}INLINE_SIM_FPU (int)sim_fpu_is (const sim_fpu *d){ switch (d->class) { case sim_fpu_class_qnan: return SIM_FPU_IS_QNAN; case sim_fpu_class_snan: return SIM_FPU_IS_SNAN; case sim_fpu_class_infinity: if (d->sign) return SIM_FPU_IS_NINF; else return SIM_FPU_IS_PINF; case sim_fpu_class_number: if (d->sign) return SIM_FPU_IS_NNUMBER; else return SIM_FPU_IS_PNUMBER; case sim_fpu_class_denorm: if (d->sign) return SIM_FPU_IS_NDENORM; else return SIM_FPU_IS_PDENORM; case sim_fpu_class_zero: if (d->sign) return SIM_FPU_IS_NZERO; else return SIM_FPU_IS_PZERO; default: return -1; abort (); }}INLINE_SIM_FPU (int)sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r){ sim_fpu res; sim_fpu_sub (&res, l, r); return sim_fpu_is (&res);}INLINE_SIM_FPU (int)sim_fpu_is_lt (const sim_fpu *l, const sim_fpu *r){ int status; sim_fpu_lt (&status, l, r); return status;}INLINE_SIM_FPU (int)sim_fpu_is_le (const sim_fpu *l, const sim_fpu *r){ int is; sim_fpu_le (&is, l, r); return is;}INLINE_SIM_FPU (int)sim_fpu_is_eq (const sim_fpu *l, const sim_fpu *r){ int is; sim_fpu_eq (&is, l, r); return is;}INLINE_SIM_FPU (int)sim_fpu_is_ne (const sim_fpu *l, const sim_fpu *r){ int is; sim_fpu_ne (&is, l, r); return is;}INLINE_SIM_FPU (int)sim_fpu_is_ge (const sim_fpu *l, const sim_fpu *r){ int is; sim_fpu_ge (&is, l, r); return is;}INLINE_SIM_FPU (int)sim_fpu_is_gt (const sim_fpu *l, const sim_fpu *r){ int is; sim_fpu_gt (&is, l, r); return is;}/* Compare operators */INLINE_SIM_FPU (int)sim_fpu_lt (int *is, const sim_fpu *l, const sim_fpu *r){ if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r)) { sim_fpu_map lval; sim_fpu_map rval; lval.i = pack_fpu (l, 1); rval.i = pack_fpu (r, 1); (*is) = (lval.d < rval.d); return 0; } else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) { *is = 0; return sim_fpu_status_invalid_snan; } else { *is = 0; return sim_fpu_status_invalid_qnan; }}INLINE_SIM_FPU (int)sim_fpu_le (int *is, const sim_fpu *l, const sim_fpu *r){ if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r)) { sim_fpu_map lval; sim_fpu_map rval; lval.i = pack_fpu (l, 1); rval.i = pack_fpu (r, 1); *is = (lval.d <= rval.d); return 0; } else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) { *is = 0; return sim_fpu_status_invalid_snan; } else { *is = 0; return sim_fpu_status_invalid_qnan; }}INLINE_SIM_FPU (int)sim_fpu_eq (int *is, const sim_fpu *l, const sim_fpu *r){ if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r)) { sim_fpu_map lval; sim_fpu_map rval; lval.i = pack_fpu (l, 1); rval.i = pack_fpu (r, 1); (*is) = (lval.d == rval.d); return 0; } else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) { *is = 0; return sim_fpu_status_invalid_snan; } else { *is = 0; return sim_fpu_status_invalid_qnan; }}INLINE_SIM_FPU (int)sim_fpu_ne (int *is, const sim_fpu *l, const sim_fpu *r){ if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r)) { sim_fpu_map lval; sim_fpu_map rval; lval.i = pack_fpu (l, 1); rval.i = pack_fpu (r, 1); (*is) = (lval.d != rval.d); return 0; } else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) { *is = 0; return sim_fpu_status_invalid_snan; } else { *is = 0; return sim_fpu_status_invalid_qnan; }}INLINE_SIM_FPU (int)sim_fpu_ge (int *is, const sim_fpu *l, const sim_fpu *r){ return sim_fpu_le (is, r, l);}INLINE_SIM_FPU (int)sim_fpu_gt (int *is, const sim_fpu *l, const sim_fpu *r){ return sim_fpu_lt (is, r, l);}/* A number of useful constants */#if EXTERN_SIM_FPU_Pconst sim_fpu sim_fpu_zero = { sim_fpu_class_zero,};const sim_fpu sim_fpu_qnan = { sim_fpu_class_qnan,};const sim_fpu sim_fpu_one = { sim_fpu_class_number, 0, IMPLICIT_1, 0};const sim_fpu sim_fpu_two = { sim_fpu_class_number, 0, IMPLICIT_1, 1};const sim_fpu sim_fpu_max32 = { sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS32), NORMAL_EXPMAX32};const sim_fpu sim_fpu_max64 = { sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS64), NORMAL_EXPMAX64};#endif/* For debugging */INLINE_SIM_FPU (void)sim_fpu_print_fpu (const sim_fpu *f, sim_fpu_print_func *print, void *arg){ sim_fpu_printn_fpu (f, print, -1, arg);}INLINE_SIM_FPU (void)sim_fpu_printn_fpu (const sim_fpu *f, sim_fpu_print_func *print, int digits, void *arg){ print (arg, "%s", f->sign ? "-" : "+"); switch (f->class) { case sim_fpu_class_qnan: print (arg, "0."); print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg); print (arg, "*QuietNaN"); break; case sim_fpu_class_snan: print (arg, "0."); print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg); print (arg, "*SignalNaN"); break; case sim_fpu_class_zero: print (arg, "0.0"); break; case sim_fpu_class_infinity: print (arg, "INF"); break; case sim_fpu_class_number: case sim_fpu_class_denorm: print (arg, "1."); print_bits (f->fraction, NR_FRAC_GUARD - 1, digits, print, arg); print (arg, "*2^%+d", f->normal_exp); ASSERT (f->fraction >= IMPLICIT_1); ASSERT (f->fraction < IMPLICIT_2); }}INLINE_SIM_FPU (void)sim_fpu_print_status (int status, sim_fpu_print_func *print, void *arg){ int i = 1; char *prefix = ""; while (status >= i) { switch ((sim_fpu_status) (status & i)) { case sim_fpu_status_denorm: print (arg, "%sD", prefix); break; case sim_fpu_status_invalid_snan: print (arg, "%sSNaN", prefix); break; case sim_fpu_status_invalid_qnan: print (arg, "%sQNaN", prefix); break; case sim_fpu_status_invalid_isi: print (arg, "%sISI", prefix); break; case sim_fpu_status_invalid_idi: print (arg, "%sIDI", prefix); break; case sim_fpu_status_invalid_zdz: print (arg, "%sZDZ", prefix); break; case sim_fpu_status_invalid_imz: print (arg, "%sIMZ", prefix); break; case sim_fpu_status_invalid_cvi: print (arg, "%sCVI", prefix); break; case sim_fpu_status_invalid_cmp: print (arg, "%sCMP", prefix); break; case sim_fpu_status_invalid_sqrt: print (arg, "%sSQRT", prefix); break; break; case sim_fpu_status_inexact: print (arg, "%sX", prefix); break; break; case sim_fpu_status_overflow: print (arg, "%sO", prefix); break; break; case sim_fpu_status_underflow: print (arg, "%sU", prefix); break; break; case sim_fpu_status_invalid_div0: print (arg, "%s/", prefix); break; break; case sim_fpu_status_rounded: print (arg, "%sR", prefix); break; break; } i <<= 1; prefix = ","; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -