📄 op_helper.c
字号:
/* Complex FPU operations which may need stack space. */#define FLOAT_ONE32 make_float32(0x3f8 << 20)#define FLOAT_ONE64 make_float64(0x3ffULL << 52)#define FLOAT_TWO32 make_float32(1 << 30)#define FLOAT_TWO64 make_float64(1ULL << 62)#define FLOAT_QNAN32 0x7fbfffff#define FLOAT_QNAN64 0x7ff7ffffffffffffULL#define FLOAT_SNAN32 0x7fffffff#define FLOAT_SNAN64 0x7fffffffffffffffULL/* convert MIPS rounding mode in FCR31 to IEEE library */unsigned int ieee_rm[] = { float_round_nearest_even, float_round_to_zero, float_round_up, float_round_down};#define RESTORE_ROUNDING_MODE \ set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status)void do_cfc1 (int reg){ switch (reg) { case 0: T0 = (int32_t)env->fpu->fcr0; break; case 25: T0 = ((env->fpu->fcr31 >> 24) & 0xfe) | ((env->fpu->fcr31 >> 23) & 0x1); break; case 26: T0 = env->fpu->fcr31 & 0x0003f07c; break; case 28: T0 = (env->fpu->fcr31 & 0x00000f83) | ((env->fpu->fcr31 >> 22) & 0x4); break; default: T0 = (int32_t)env->fpu->fcr31; break; }}void do_ctc1 (int reg){ switch(reg) { case 25: if (T0 & 0xffffff00) return; env->fpu->fcr31 = (env->fpu->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) | ((T0 & 0x1) << 23); break; case 26: if (T0 & 0x007c0000) return; env->fpu->fcr31 = (env->fpu->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c); break; case 28: if (T0 & 0x007c0000) return; env->fpu->fcr31 = (env->fpu->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) | ((T0 & 0x4) << 22); break; case 31: if (T0 & 0x007c0000) return; env->fpu->fcr31 = T0; break; default: return; } /* set rounding mode */ RESTORE_ROUNDING_MODE; set_float_exception_flags(0, &env->fpu->fp_status); if ((GET_FP_ENABLE(env->fpu->fcr31) | 0x20) & GET_FP_CAUSE(env->fpu->fcr31)) do_raise_exception(EXCP_FPE);}static always_inline char ieee_ex_to_mips(char xcpt){ return (xcpt & float_flag_inexact) >> 5 | (xcpt & float_flag_underflow) >> 3 | (xcpt & float_flag_overflow) >> 1 | (xcpt & float_flag_divbyzero) << 1 | (xcpt & float_flag_invalid) << 4;}static always_inline char mips_ex_to_ieee(char xcpt){ return (xcpt & FP_INEXACT) << 5 | (xcpt & FP_UNDERFLOW) << 3 | (xcpt & FP_OVERFLOW) << 1 | (xcpt & FP_DIV0) >> 1 | (xcpt & FP_INVALID) >> 4;}static always_inline void update_fcr31(void){ int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status)); SET_FP_CAUSE(env->fpu->fcr31, tmp); if (GET_FP_ENABLE(env->fpu->fcr31) & tmp) do_raise_exception(EXCP_FPE); else UPDATE_FP_FLAGS(env->fpu->fcr31, tmp);}#define FLOAT_OP(name, p) void do_float_##name##_##p(void)FLOAT_OP(cvtd, s){ set_float_exception_flags(0, &env->fpu->fp_status); FDT2 = float32_to_float64(FST0, &env->fpu->fp_status); update_fcr31();}FLOAT_OP(cvtd, w){ set_float_exception_flags(0, &env->fpu->fp_status); FDT2 = int32_to_float64(WT0, &env->fpu->fp_status); update_fcr31();}FLOAT_OP(cvtd, l){ set_float_exception_flags(0, &env->fpu->fp_status); FDT2 = int64_to_float64(DT0, &env->fpu->fp_status); update_fcr31();}FLOAT_OP(cvtl, d){ set_float_exception_flags(0, &env->fpu->fp_status); DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(cvtl, s){ set_float_exception_flags(0, &env->fpu->fp_status); DT2 = float32_to_int64(FST0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(cvtps, pw){ set_float_exception_flags(0, &env->fpu->fp_status); FST2 = int32_to_float32(WT0, &env->fpu->fp_status); FSTH2 = int32_to_float32(WTH0, &env->fpu->fp_status); update_fcr31();}FLOAT_OP(cvtpw, ps){ set_float_exception_flags(0, &env->fpu->fp_status); WT2 = float32_to_int32(FST0, &env->fpu->fp_status); WTH2 = float32_to_int32(FSTH0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(cvts, d){ set_float_exception_flags(0, &env->fpu->fp_status); FST2 = float64_to_float32(FDT0, &env->fpu->fp_status); update_fcr31();}FLOAT_OP(cvts, w){ set_float_exception_flags(0, &env->fpu->fp_status); FST2 = int32_to_float32(WT0, &env->fpu->fp_status); update_fcr31();}FLOAT_OP(cvts, l){ set_float_exception_flags(0, &env->fpu->fp_status); FST2 = int64_to_float32(DT0, &env->fpu->fp_status); update_fcr31();}FLOAT_OP(cvts, pl){ set_float_exception_flags(0, &env->fpu->fp_status); WT2 = WT0; update_fcr31();}FLOAT_OP(cvts, pu){ set_float_exception_flags(0, &env->fpu->fp_status); WT2 = WTH0; update_fcr31();}FLOAT_OP(cvtw, s){ set_float_exception_flags(0, &env->fpu->fp_status); WT2 = float32_to_int32(FST0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(cvtw, d){ set_float_exception_flags(0, &env->fpu->fp_status); WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(roundl, d){ set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(roundl, s){ set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); DT2 = float32_to_int64(FST0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(roundw, d){ set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(roundw, s){ set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status); WT2 = float32_to_int32(FST0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(truncl, d){ DT2 = float64_to_int64_round_to_zero(FDT0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(truncl, s){ DT2 = float32_to_int64_round_to_zero(FST0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(truncw, d){ WT2 = float64_to_int32_round_to_zero(FDT0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(truncw, s){ WT2 = float32_to_int32_round_to_zero(FST0, &env->fpu->fp_status); update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(ceill, d){ set_float_rounding_mode(float_round_up, &env->fpu->fp_status); DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(ceill, s){ set_float_rounding_mode(float_round_up, &env->fpu->fp_status); DT2 = float32_to_int64(FST0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(ceilw, d){ set_float_rounding_mode(float_round_up, &env->fpu->fp_status); WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(ceilw, s){ set_float_rounding_mode(float_round_up, &env->fpu->fp_status); WT2 = float32_to_int32(FST0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(floorl, d){ set_float_rounding_mode(float_round_down, &env->fpu->fp_status); DT2 = float64_to_int64(FDT0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(floorl, s){ set_float_rounding_mode(float_round_down, &env->fpu->fp_status); DT2 = float32_to_int64(FST0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) DT2 = FLOAT_SNAN64;}FLOAT_OP(floorw, d){ set_float_rounding_mode(float_round_down, &env->fpu->fp_status); WT2 = float64_to_int32(FDT0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}FLOAT_OP(floorw, s){ set_float_rounding_mode(float_round_down, &env->fpu->fp_status); WT2 = float32_to_int32(FST0, &env->fpu->fp_status); RESTORE_ROUNDING_MODE; update_fcr31(); if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) WT2 = FLOAT_SNAN32;}/* MIPS specific unary operations */FLOAT_OP(recip, d){ set_float_exception_flags(0, &env->fpu->fp_status); FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status); update_fcr31();}FLOAT_OP(recip, s){ set_float_exception_flags(0, &env->fpu->fp_status);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -