?? op_helper.c
字號:
} else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) { /* qNan / infinity conversion */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI); } else { p.i = float64_to_int64(FT0, &env->fp_status); FT0 = p.d; }}void do_fctidz (void){ union { double d; uint64_t i; } p; if (unlikely(float64_is_signaling_nan(FT0))) { /* sNaN conversion */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI); } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) { /* qNan / infinity conversion */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI); } else { p.i = float64_to_int64_round_to_zero(FT0, &env->fp_status); FT0 = p.d; }}#endifstatic always_inline void do_fri (int rounding_mode){ if (unlikely(float64_is_signaling_nan(FT0))) { /* sNaN round */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI); } else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) { /* qNan / infinity round */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI); } else { set_float_rounding_mode(rounding_mode, &env->fp_status); FT0 = float64_round_to_int(FT0, &env->fp_status); /* Restore rounding mode from FPSCR */ fpscr_set_rounding_mode(); }}void do_frin (void){ do_fri(float_round_nearest_even);}void do_friz (void){ do_fri(float_round_to_zero);}void do_frip (void){ do_fri(float_round_up);}void do_frim (void){ do_fri(float_round_down);}#if USE_PRECISE_EMULATIONvoid do_fmadd (void){ if (unlikely(float64_is_signaling_nan(FT0) || float64_is_signaling_nan(FT1) || float64_is_signaling_nan(FT2))) { /* sNaN operation */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else {#ifdef FLOAT128 /* This is the way the PowerPC specification defines it */ float128 ft0_128, ft1_128; ft0_128 = float64_to_float128(FT0, &env->fp_status); ft1_128 = float64_to_float128(FT1, &env->fp_status); ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); ft1_128 = float64_to_float128(FT2, &env->fp_status); ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); FT0 = float128_to_float64(ft0_128, &env->fp_status);#else /* This is OK on x86 hosts */ FT0 = (FT0 * FT1) + FT2;#endif }}void do_fmsub (void){ if (unlikely(float64_is_signaling_nan(FT0) || float64_is_signaling_nan(FT1) || float64_is_signaling_nan(FT2))) { /* sNaN operation */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else {#ifdef FLOAT128 /* This is the way the PowerPC specification defines it */ float128 ft0_128, ft1_128; ft0_128 = float64_to_float128(FT0, &env->fp_status); ft1_128 = float64_to_float128(FT1, &env->fp_status); ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); ft1_128 = float64_to_float128(FT2, &env->fp_status); ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); FT0 = float128_to_float64(ft0_128, &env->fp_status);#else /* This is OK on x86 hosts */ FT0 = (FT0 * FT1) - FT2;#endif }}#endif /* USE_PRECISE_EMULATION */void do_fnmadd (void){ if (unlikely(float64_is_signaling_nan(FT0) || float64_is_signaling_nan(FT1) || float64_is_signaling_nan(FT2))) { /* sNaN operation */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else {#if USE_PRECISE_EMULATION#ifdef FLOAT128 /* This is the way the PowerPC specification defines it */ float128 ft0_128, ft1_128; ft0_128 = float64_to_float128(FT0, &env->fp_status); ft1_128 = float64_to_float128(FT1, &env->fp_status); ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); ft1_128 = float64_to_float128(FT2, &env->fp_status); ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status); FT0 = float128_to_float64(ft0_128, &env->fp_status);#else /* This is OK on x86 hosts */ FT0 = (FT0 * FT1) + FT2;#endif#else FT0 = float64_mul(FT0, FT1, &env->fp_status); FT0 = float64_add(FT0, FT2, &env->fp_status);#endif if (likely(!isnan(FT0))) FT0 = float64_chs(FT0); }}void do_fnmsub (void){ if (unlikely(float64_is_signaling_nan(FT0) || float64_is_signaling_nan(FT1) || float64_is_signaling_nan(FT2))) { /* sNaN operation */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else {#if USE_PRECISE_EMULATION#ifdef FLOAT128 /* This is the way the PowerPC specification defines it */ float128 ft0_128, ft1_128; ft0_128 = float64_to_float128(FT0, &env->fp_status); ft1_128 = float64_to_float128(FT1, &env->fp_status); ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status); ft1_128 = float64_to_float128(FT2, &env->fp_status); ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status); FT0 = float128_to_float64(ft0_128, &env->fp_status);#else /* This is OK on x86 hosts */ FT0 = (FT0 * FT1) - FT2;#endif#else FT0 = float64_mul(FT0, FT1, &env->fp_status); FT0 = float64_sub(FT0, FT2, &env->fp_status);#endif if (likely(!isnan(FT0))) FT0 = float64_chs(FT0); }}#if USE_PRECISE_EMULATIONvoid do_frsp (void){ if (unlikely(float64_is_signaling_nan(FT0))) { /* sNaN square root */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else { FT0 = float64_to_float32(FT0, &env->fp_status); }}#endif /* USE_PRECISE_EMULATION */void do_fsqrt (void){ if (unlikely(float64_is_signaling_nan(FT0))) { /* sNaN square root */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) { /* Square root of a negative nonzero number */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT); } else { FT0 = float64_sqrt(FT0, &env->fp_status); }}void do_fre (void){ union { double d; uint64_t i; } p; if (unlikely(float64_is_signaling_nan(FT0))) { /* sNaN reciprocal */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else if (unlikely(iszero(FT0))) { /* Zero reciprocal */ float_zero_divide_excp(); } else if (likely(isnormal(FT0))) { FT0 = float64_div(1.0, FT0, &env->fp_status); } else { p.d = FT0; if (p.i == 0x8000000000000000ULL) { p.i = 0xFFF0000000000000ULL; } else if (p.i == 0x0000000000000000ULL) { p.i = 0x7FF0000000000000ULL; } else if (isnan(FT0)) { p.i = 0x7FF8000000000000ULL; } else if (fpisneg(FT0)) { p.i = 0x8000000000000000ULL; } else { p.i = 0x0000000000000000ULL; } FT0 = p.d; }}void do_fres (void){ union { double d; uint64_t i; } p; if (unlikely(float64_is_signaling_nan(FT0))) { /* sNaN reciprocal */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else if (unlikely(iszero(FT0))) { /* Zero reciprocal */ float_zero_divide_excp(); } else if (likely(isnormal(FT0))) {#if USE_PRECISE_EMULATION FT0 = float64_div(1.0, FT0, &env->fp_status); FT0 = float64_to_float32(FT0, &env->fp_status);#else FT0 = float32_div(1.0, FT0, &env->fp_status);#endif } else { p.d = FT0; if (p.i == 0x8000000000000000ULL) { p.i = 0xFFF0000000000000ULL; } else if (p.i == 0x0000000000000000ULL) { p.i = 0x7FF0000000000000ULL; } else if (isnan(FT0)) { p.i = 0x7FF8000000000000ULL; } else if (fpisneg(FT0)) { p.i = 0x8000000000000000ULL; } else { p.i = 0x0000000000000000ULL; } FT0 = p.d; }}void do_frsqrte (void){ union { double d; uint64_t i; } p; if (unlikely(float64_is_signaling_nan(FT0))) { /* sNaN reciprocal square root */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else if (unlikely(fpisneg(FT0) && !iszero(FT0))) { /* Reciprocal square root of a negative nonzero number */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT); } else if (likely(isnormal(FT0))) { FT0 = float64_sqrt(FT0, &env->fp_status); FT0 = float32_div(1.0, FT0, &env->fp_status); } else { p.d = FT0; if (p.i == 0x8000000000000000ULL) { p.i = 0xFFF0000000000000ULL; } else if (p.i == 0x0000000000000000ULL) { p.i = 0x7FF0000000000000ULL; } else if (isnan(FT0)) { p.i |= 0x000FFFFFFFFFFFFFULL; } else if (fpisneg(FT0)) { p.i = 0x7FF8000000000000ULL; } else { p.i = 0x0000000000000000ULL; } FT0 = p.d; }}void do_fsel (void){ if (!fpisneg(FT0) || iszero(FT0)) FT0 = FT1; else FT0 = FT2;}void do_fcmpu (void){ if (unlikely(float64_is_signaling_nan(FT0) || float64_is_signaling_nan(FT1))) { /* sNaN comparison */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN); } else { if (float64_lt(FT0, FT1, &env->fp_status)) { T0 = 0x08UL; } else if (!float64_le(FT0, FT1, &env->fp_status)) { T0 = 0x04UL; } else { T0 = 0x02UL; } } env->fpscr &= ~(0x0F << FPSCR_FPRF); env->fpscr |= T0 << FPSCR_FPRF;}void do_fcmpo (void){ if (unlikely(float64_is_nan(FT0) || float64_is_nan(FT1))) { if (float64_is_signaling_nan(FT0) || float64_is_signaling_nan(FT1)) { /* sNaN comparison */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXVC); } else { /* qNaN comparison */ fload_invalid_op_excp(POWERPC_EXCP_FP_VXVC); } } else { if (float64_lt(FT0, FT1, &env->fp_status)) { T0 = 0x08UL; } else if (!float64_le(FT0, FT1, &env->fp_status)) { T0 = 0x04UL; } else { T0 = 0x02UL; } } env->fpscr &= ~(0x0F << FPSCR_FPRF); env->fpscr |= T0 << FPSCR_FPRF;}#if !defined (CONFIG_USER_ONLY)void cpu_dump_rfi (target_ulong RA, target_ulong msr);void do_store_msr (void){ T0 = hreg_store_msr(env, T0, 0); if (T0 != 0) { env->interrupt_request |= CPU_INTERRUPT_EXITTB; do_raise_exception(T0); }}static always_inline void __do_rfi (target_ulong nip, target_ulong msr, target_ulong msrm, int keep_msrh){#if defined(TARGET_PPC64) if (msr & (1ULL << MSR_SF)) { nip = (uint64_t)nip; msr &= (uint64_t)msrm; } else { nip = (uint32_t)nip; msr = (uint32_t)(msr & msrm); if (keep_msrh) msr |= env->msr & ~((uint64_t)0xFFFFFFFF); }#else nip = (uint32_t)nip; msr &= (uint32_t)msrm;#endif /* XXX: beware: this is false if VLE is supported */ env->nip = nip & ~((target_ulong)0x00000003); hreg_store_msr(env, msr, 1);#if defined (DEBUG_OP) cpu_dump_rfi(env->nip, env->msr);#endif /* No need to raise an exception here, * as rfi is always the last insn of a TB */ env->interrupt_request |= CPU_INTERRUPT_EXITTB;}void do_rfi (void){ __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1], ~((target_ulong)0xFFFF0000), 1);}#if defined(TARGET_PPC64)void do_rfid (void){ __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1], ~((target_ulong)0xFFFF0000), 0);}void do_hrfid (void){ __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1], ~((target_ulong)0xFFFF0000), 0);}#endif#endifvoid do_tw (int flags){ if (!likely(!(((int32_t)T0 < (int32_t)T1 && (flags & 0x10)) || ((int32_t)T0 > (int32_t)T1 && (flags & 0x08)) || ((int32_t)T0 == (int32_t)T1 && (flags & 0x04)) || ((uint32_t)T0 < (uint32_t)T1 && (flags & 0x02)) || ((uint32_t)T0 > (uint32_t)T1 && (flags & 0x01))))) { do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP); }}#if defined(TARGET_PPC64)void do_td (int flags){ if (!likely(!(((int64_t)T0 < (int64_t)T1 && (flags & 0x10)) || ((int64_t)T0 > (int64_t)T1 && (flags & 0x08)) || ((int64_t)T0 == (int64_t)T1 && (flags & 0x04)) || ((uint64_t)T0 < (uint64_t)T1 && (flags & 0x02)) || ((uint64_t)T0 > (uint64_t)T1 && (flags & 0x01))))) do_raise_exception_err(POWERPC_EXCP_PROGRAM, POWERPC_EXCP_TRAP);}#endif/*****************************************************************************//* PowerPC 601 specific instructions (POWER bridge) */void do_POWER_abso (void){ if ((int32_t)T0 == INT32_MIN) { T0 = INT32_MAX; xer_ov = 1; } else if ((int32_t)T0 < 0) { T0 = -T0; xer_ov = 0; } else { xer_ov = 0; } xer_so |= xer_ov;}void do_POWER_clcs (void){ switch (T0) { case 0x0CUL: /* Instruction cache line size */ T0 = env->icache_line_size; break; case 0x0DUL: /* Data cache line size */ T0 = env->dcache_line_size; break; case 0x0EUL: /* Minimum cache line size */ T0 = env->icache_line_size < env->dcache_line_size ? env->icache_line_size : env->dcache_line_size; break; case 0x0FUL: /* Maximum cache line size */ T0 = env->icache_line_size > env->dcache_line_size ? env->icache_line_size : env->dcache_line_size; break; default: /* Undefined */ break; }}void do_POWER_div (void){ uint64_t tmp; if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || (int32_t)T1 == 0) { T0 = UINT32_MAX * ((uint32_t)T0 >> 31); env->spr[SPR_MQ] = 0; } else { tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ]; env->spr[SPR_MQ] = tmp % T1; T0 = tmp / (int32_t)T1; }}void do_POWER_divo (void){ int64_t tmp; if (((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) || (int32_t)T1 == 0) { T0 = UINT32_MAX * ((uint32_t)T0 >> 31); env->spr[SPR_MQ] = 0; xer_ov = 1; } else { tmp = ((uint64_t)T0 << 32) | env->spr[SPR_MQ]; env->spr[SPR_MQ] = tmp % T1; tmp /= (int32_t)T1; if (tmp > (int64_t)INT32_MAX || tmp < (int64_t)INT32_MIN) { xer_ov = 1; } else { xer_ov = 0; } T0 = tmp; } xer_so |= xer_ov;}void do_POWER_divs (void){
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -