mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Fix PowerPC FPSCR update and floating-point exception generation
in most useful cases. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3458 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
+1
-6
@@ -224,11 +224,6 @@ void cpu_loop(CPUPPCState *env)
|
||||
case POWERPC_EXCP_FP:
|
||||
EXCP_DUMP(env, "Floating point program exception\n");
|
||||
/* Set FX */
|
||||
env->fpscr[7] |= 0x8;
|
||||
/* Finally, update FEX */
|
||||
if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
|
||||
((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
|
||||
env->fpscr[7] |= 0x4;
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
switch (env->error_code & 0xF) {
|
||||
@@ -248,7 +243,7 @@ void cpu_loop(CPUPPCState *env)
|
||||
case POWERPC_EXCP_FP_VXSOFT:
|
||||
info.si_code = FPE_FLTINV;
|
||||
break;
|
||||
case POWERPC_EXCP_FP_VXNAN:
|
||||
case POWERPC_EXCP_FP_VXSNAN:
|
||||
case POWERPC_EXCP_FP_VXISI:
|
||||
case POWERPC_EXCP_FP_VXIDI:
|
||||
case POWERPC_EXCP_FP_VXIMZ:
|
||||
|
||||
+1
-7
@@ -829,12 +829,6 @@ void cpu_loop(CPUPPCState *env)
|
||||
switch (env->error_code & ~0xF) {
|
||||
case POWERPC_EXCP_FP:
|
||||
EXCP_DUMP(env, "Floating point program exception\n");
|
||||
/* Set FX */
|
||||
env->fpscr[7] |= 0x8;
|
||||
/* Finally, update FEX */
|
||||
if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
|
||||
((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
|
||||
env->fpscr[7] |= 0x4;
|
||||
info.si_signo = TARGET_SIGFPE;
|
||||
info.si_errno = 0;
|
||||
switch (env->error_code & 0xF) {
|
||||
@@ -854,7 +848,7 @@ void cpu_loop(CPUPPCState *env)
|
||||
case POWERPC_EXCP_FP_VXSOFT:
|
||||
info.si_code = TARGET_FPE_FLTINV;
|
||||
break;
|
||||
case POWERPC_EXCP_FP_VXNAN:
|
||||
case POWERPC_EXCP_FP_VXSNAN:
|
||||
case POWERPC_EXCP_FP_VXISI:
|
||||
case POWERPC_EXCP_FP_VXIDI:
|
||||
case POWERPC_EXCP_FP_VXIMZ:
|
||||
|
||||
+74
-4
@@ -239,7 +239,7 @@ enum {
|
||||
POWERPC_EXCP_FP_UX = 0x02, /* FP underflow */
|
||||
POWERPC_EXCP_FP_ZX = 0x03, /* FP divide by zero */
|
||||
POWERPC_EXCP_FP_XX = 0x04, /* FP inexact */
|
||||
POWERPC_EXCP_FP_VXNAN = 0x05, /* FP invalid SNaN op */
|
||||
POWERPC_EXCP_FP_VXSNAN = 0x05, /* FP invalid SNaN op */
|
||||
POWERPC_EXCP_FP_VXISI = 0x06, /* FP invalid infinite subtraction */
|
||||
POWERPC_EXCP_FP_VXIDI = 0x07, /* FP invalid infinite divide */
|
||||
POWERPC_EXCP_FP_VXZDZ = 0x08, /* FP invalid zero divide */
|
||||
@@ -433,14 +433,84 @@ enum {
|
||||
POWERPC_FLAG_PMM = 0x00000400,
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Floating point status and control register */
|
||||
#define FPSCR_FX 31 /* Floating-point exception summary */
|
||||
#define FPSCR_FEX 30 /* Floating-point enabled exception summary */
|
||||
#define FPSCR_VX 29 /* Floating-point invalid operation exception summ. */
|
||||
#define FPSCR_OX 28 /* Floating-point overflow exception */
|
||||
#define FPSCR_UX 27 /* Floating-point underflow exception */
|
||||
#define FPSCR_ZX 26 /* Floating-point zero divide exception */
|
||||
#define FPSCR_XX 25 /* Floating-point inexact exception */
|
||||
#define FPSCR_VXSNAN 24 /* Floating-point invalid operation exception (sNan) */
|
||||
#define FPSCR_VXISI 23 /* Floating-point invalid operation exception (inf) */
|
||||
#define FPSCR_VXIDI 22 /* Floating-point invalid operation exception (inf) */
|
||||
#define FPSCR_VXZDZ 21 /* Floating-point invalid operation exception (zero) */
|
||||
#define FPSCR_VXIMZ 20 /* Floating-point invalid operation exception (inf) */
|
||||
#define FPSCR_VXVC 19 /* Floating-point invalid operation exception (comp) */
|
||||
#define FPSCR_FR 18 /* Floating-point fraction rounded */
|
||||
#define FPSCR_FI 17 /* Floating-point fraction inexact */
|
||||
#define FPSCR_C 16 /* Floating-point result class descriptor */
|
||||
#define FPSCR_FL 15 /* Floating-point less than or negative */
|
||||
#define FPSCR_FG 14 /* Floating-point greater than or negative */
|
||||
#define FPSCR_FE 13 /* Floating-point equal or zero */
|
||||
#define FPSCR_FU 12 /* Floating-point unordered or NaN */
|
||||
#define FPSCR_FPCC 12 /* Floating-point condition code */
|
||||
#define FPSCR_FPRF 12 /* Floating-point result flags */
|
||||
#define FPSCR_VXSOFT 10 /* Floating-point invalid operation exception (soft) */
|
||||
#define FPSCR_VXSQRT 9 /* Floating-point invalid operation exception (sqrt) */
|
||||
#define FPSCR_VXCVI 8 /* Floating-point invalid operation exception (int) */
|
||||
#define FPSCR_VE 7 /* Floating-point invalid operation exception enable */
|
||||
#define FPSCR_OE 6 /* Floating-point overflow exception enable */
|
||||
#define FPSCR_UE 5 /* Floating-point undeflow exception enable */
|
||||
#define FPSCR_ZE 4 /* Floating-point zero divide exception enable */
|
||||
#define FPSCR_XE 3 /* Floating-point inexact exception enable */
|
||||
#define FPSCR_NI 2 /* Floating-point non-IEEE mode */
|
||||
#define FPSCR_RN1 1
|
||||
#define FPSCR_RN 0 /* Floating-point rounding control */
|
||||
#define fpscr_fex (((env->fpscr) >> FPSCR_FEX) & 0x1)
|
||||
#define fpscr_vx (((env->fpscr) >> FPSCR_VX) & 0x1)
|
||||
#define fpscr_ox (((env->fpscr) >> FPSCR_OX) & 0x1)
|
||||
#define fpscr_ux (((env->fpscr) >> FPSCR_UX) & 0x1)
|
||||
#define fpscr_zx (((env->fpscr) >> FPSCR_ZX) & 0x1)
|
||||
#define fpscr_xx (((env->fpscr) >> FPSCR_XX) & 0x1)
|
||||
#define fpscr_vxsnan (((env->fpscr) >> FPSCR_VXSNAN) & 0x1)
|
||||
#define fpscr_vxisi (((env->fpscr) >> FPSCR_VXISI) & 0x1)
|
||||
#define fpscr_vxidi (((env->fpscr) >> FPSCR_VXIDI) & 0x1)
|
||||
#define fpscr_vxzdz (((env->fpscr) >> FPSCR_VXZDZ) & 0x1)
|
||||
#define fpscr_vximz (((env->fpscr) >> FPSCR_VXIMZ) & 0x1)
|
||||
#define fpscr_vxvc (((env->fpscr) >> FPSCR_VXVC) & 0x1)
|
||||
#define fpscr_fpcc (((env->fpscr) >> FPSCR_FPCC) & 0xF)
|
||||
#define fpscr_vxsoft (((env->fpscr) >> FPSCR_VXSOFT) & 0x1)
|
||||
#define fpscr_vxsqrt (((env->fpscr) >> FPSCR_VXSQRT) & 0x1)
|
||||
#define fpscr_vxcvi (((env->fpscr) >> FPSCR_VXCVI) & 0x1)
|
||||
#define fpscr_ve (((env->fpscr) >> FPSCR_VE) & 0x1)
|
||||
#define fpscr_oe (((env->fpscr) >> FPSCR_OE) & 0x1)
|
||||
#define fpscr_ue (((env->fpscr) >> FPSCR_UE) & 0x1)
|
||||
#define fpscr_ze (((env->fpscr) >> FPSCR_ZE) & 0x1)
|
||||
#define fpscr_xe (((env->fpscr) >> FPSCR_XE) & 0x1)
|
||||
#define fpscr_ni (((env->fpscr) >> FPSCR_NI) & 0x1)
|
||||
#define fpscr_rn (((env->fpscr) >> FPSCR_RN) & 0x3)
|
||||
/* Invalid operation exception summary */
|
||||
#define fpscr_ix ((env->fpscr) & ((1 << FPSCR_VXSNAN) | (1 << FPSCR_VXISI) | \
|
||||
(1 << FPSCR_VXIDI) | (1 << FPSCR_VXZDZ) | \
|
||||
(1 << FPSCR_VXIMZ) | (1 << FPSCR_VXVC) | \
|
||||
(1 << FPSCR_VXSOFT) | (1 << FPSCR_VXSQRT) | \
|
||||
(1 << FPSCR_VXCVI)))
|
||||
/* exception summary */
|
||||
#define fpscr_ex (((env->fpscr) >> FPSCR_XX) & 0x1F)
|
||||
/* enabled exception summary */
|
||||
#define fpscr_eex (((env->fpscr) >> FPSCR_XX) & ((env->fpscr) >> FPSCR_XE) & \
|
||||
0x1F)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* The whole PowerPC CPU context */
|
||||
#if defined(TARGET_PPC64H)
|
||||
#define NB_MMU_MODES 3
|
||||
#else
|
||||
#define NB_MMU_MODES 2
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* The whole PowerPC CPU context */
|
||||
struct CPUPPCState {
|
||||
/* First are the most commonly used resources
|
||||
* during translated code execution
|
||||
@@ -482,7 +552,7 @@ struct CPUPPCState {
|
||||
/* floating point registers */
|
||||
float64 fpr[32];
|
||||
/* floating point status and control register */
|
||||
uint8_t fpscr[8];
|
||||
uint32_t fpscr;
|
||||
|
||||
CPU_COMMON
|
||||
|
||||
|
||||
+6
-7
@@ -2130,6 +2130,8 @@ static always_inline void powerpc_excp (CPUState *env,
|
||||
fprintf(logfile, "Ignore floating point exception\n");
|
||||
}
|
||||
#endif
|
||||
env->exception_index = POWERPC_EXCP_NONE;
|
||||
env->error_code = 0;
|
||||
return;
|
||||
}
|
||||
new_msr &= ~((target_ulong)1 << MSR_RI);
|
||||
@@ -2138,12 +2140,6 @@ static always_inline void powerpc_excp (CPUState *env,
|
||||
new_msr |= (target_ulong)1 << MSR_HV;
|
||||
#endif
|
||||
msr |= 0x00100000;
|
||||
/* Set FX */
|
||||
env->fpscr[7] |= 0x8;
|
||||
/* Finally, update FEX */
|
||||
if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
|
||||
((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
|
||||
env->fpscr[7] |= 0x4;
|
||||
if (msr_fe0 != msr_fe1) {
|
||||
msr |= 0x00010000;
|
||||
goto store_current;
|
||||
@@ -2199,8 +2195,11 @@ static always_inline void powerpc_excp (CPUState *env,
|
||||
/* XXX: To be removed */
|
||||
if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
|
||||
env->osi_call) {
|
||||
if (env->osi_call(env) != 0)
|
||||
if (env->osi_call(env) != 0) {
|
||||
env->exception_index = POWERPC_EXCP_NONE;
|
||||
env->error_code = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (loglevel & CPU_LOG_INT) {
|
||||
dump_syscall(env);
|
||||
|
||||
+115
-15
@@ -135,13 +135,6 @@ void OPPROTO op_set_Rc0 (void)
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* Set Rc1 (for floating point arithmetic) */
|
||||
void OPPROTO op_set_Rc1 (void)
|
||||
{
|
||||
env->crf[1] = env->fpscr[7];
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* Constants load */
|
||||
void OPPROTO op_reset_T0 (void)
|
||||
{
|
||||
@@ -552,9 +545,102 @@ void OPPROTO op_store_dbatl (void)
|
||||
#endif /* !defined(CONFIG_USER_ONLY) */
|
||||
|
||||
/* FPSCR */
|
||||
void OPPROTO op_load_fpscr (void)
|
||||
#ifdef CONFIG_SOFTFLOAT
|
||||
void OPPROTO op_reset_fpstatus (void)
|
||||
{
|
||||
do_load_fpscr();
|
||||
env->fp_status.float_exception_flags = 0;
|
||||
RETURN();
|
||||
}
|
||||
#endif
|
||||
|
||||
void OPPROTO op_compute_fprf (void)
|
||||
{
|
||||
do_compute_fprf(PARAM1);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SOFTFLOAT
|
||||
void OPPROTO op_float_check_status (void)
|
||||
{
|
||||
do_float_check_status();
|
||||
RETURN();
|
||||
}
|
||||
#else
|
||||
void OPPROTO op_float_check_status (void)
|
||||
{
|
||||
if (env->exception_index == POWERPC_EXCP_PROGRAM &&
|
||||
(env->error_code & POWERPC_EXCP_FP)) {
|
||||
/* Differred floating-point exception after target FPR update */
|
||||
if (msr_fe0 != 0 || msr_fe1 != 0)
|
||||
do_raise_exception_err(env->exception_index, env->error_code);
|
||||
}
|
||||
RETURN();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
#define WORD0 0
|
||||
#define WORD1 1
|
||||
#else
|
||||
#define WORD0 1
|
||||
#define WORD1 0
|
||||
#endif
|
||||
void OPPROTO op_load_fpscr_FT0 (void)
|
||||
{
|
||||
/* The 32 MSB of the target fpr are undefined.
|
||||
* They'll be zero...
|
||||
*/
|
||||
union {
|
||||
float64 d;
|
||||
struct {
|
||||
uint32_t u[2];
|
||||
} s;
|
||||
} u;
|
||||
|
||||
u.s.u[WORD0] = 0;
|
||||
u.s.u[WORD1] = env->fpscr;
|
||||
FT0 = u.d;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_set_FT0 (void)
|
||||
{
|
||||
union {
|
||||
float64 d;
|
||||
struct {
|
||||
uint32_t u[2];
|
||||
} s;
|
||||
} u;
|
||||
|
||||
u.s.u[WORD0] = 0;
|
||||
u.s.u[WORD1] = PARAM1;
|
||||
FT0 = u.d;
|
||||
RETURN();
|
||||
}
|
||||
#undef WORD0
|
||||
#undef WORD1
|
||||
|
||||
void OPPROTO op_load_fpscr_T0 (void)
|
||||
{
|
||||
T0 = (env->fpscr >> PARAM1) & 0xF;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_load_fpcc (void)
|
||||
{
|
||||
T0 = fpscr_fpcc;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_fpscr_resetbit (void)
|
||||
{
|
||||
env->fpscr &= PARAM1;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_fpscr_setbit (void)
|
||||
{
|
||||
do_fpscr_setbit(PARAM1);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
@@ -564,12 +650,6 @@ void OPPROTO op_store_fpscr (void)
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO op_reset_scrfx (void)
|
||||
{
|
||||
env->fpscr[7] &= ~0x8;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* crf operations */
|
||||
void OPPROTO op_getbit_T0 (void)
|
||||
{
|
||||
@@ -1702,28 +1782,44 @@ void OPPROTO op_srli_T1_64 (void)
|
||||
/* fadd - fadd. */
|
||||
void OPPROTO op_fadd (void)
|
||||
{
|
||||
#if USE_PRECISE_EMULATION
|
||||
do_fadd();
|
||||
#else
|
||||
FT0 = float64_add(FT0, FT1, &env->fp_status);
|
||||
#endif
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* fsub - fsub. */
|
||||
void OPPROTO op_fsub (void)
|
||||
{
|
||||
#if USE_PRECISE_EMULATION
|
||||
do_fsub();
|
||||
#else
|
||||
FT0 = float64_sub(FT0, FT1, &env->fp_status);
|
||||
#endif
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* fmul - fmul. */
|
||||
void OPPROTO op_fmul (void)
|
||||
{
|
||||
#if USE_PRECISE_EMULATION
|
||||
do_fmul();
|
||||
#else
|
||||
FT0 = float64_mul(FT0, FT1, &env->fp_status);
|
||||
#endif
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* fdiv - fdiv. */
|
||||
void OPPROTO op_fdiv (void)
|
||||
{
|
||||
#if USE_PRECISE_EMULATION
|
||||
do_fdiv();
|
||||
#else
|
||||
FT0 = float64_div(FT0, FT1, &env->fp_status);
|
||||
#endif
|
||||
RETURN();
|
||||
}
|
||||
|
||||
@@ -1805,7 +1901,11 @@ void OPPROTO op_fnmsub (void)
|
||||
/* frsp - frsp. */
|
||||
void OPPROTO op_frsp (void)
|
||||
{
|
||||
#if USE_PRECISE_EMULATION
|
||||
do_frsp();
|
||||
#else
|
||||
FT0 = float64_to_float32(FT0, &env->fp_status);
|
||||
#endif
|
||||
RETURN();
|
||||
}
|
||||
|
||||
|
||||
+736
-175
File diff suppressed because it is too large
Load Diff
+14
-1
@@ -60,7 +60,7 @@ void do_store_cr (uint32_t mask);
|
||||
#if defined(TARGET_PPC64)
|
||||
void do_store_pri (int prio);
|
||||
#endif
|
||||
void do_load_fpscr (void);
|
||||
void do_fpscr_setbit (int bit);
|
||||
void do_store_fpscr (uint32_t mask);
|
||||
target_ulong ppc_load_dump_spr (int sprn);
|
||||
void ppc_store_dump_spr (int sprn, target_ulong val);
|
||||
@@ -94,6 +94,16 @@ void do_popcntb_64 (void);
|
||||
#endif
|
||||
|
||||
/* Floating-point arithmetic helpers */
|
||||
void do_compute_fprf (int set_class);
|
||||
#ifdef CONFIG_SOFTFLOAT
|
||||
void do_float_check_status (void);
|
||||
#endif
|
||||
#if USE_PRECISE_EMULATION
|
||||
void do_fadd (void);
|
||||
void do_fsub (void);
|
||||
void do_fmul (void);
|
||||
void do_fdiv (void);
|
||||
#endif
|
||||
void do_fsqrt (void);
|
||||
void do_fre (void);
|
||||
void do_fres (void);
|
||||
@@ -105,6 +115,9 @@ void do_fmsub (void);
|
||||
#endif
|
||||
void do_fnmadd (void);
|
||||
void do_fnmsub (void);
|
||||
#if USE_PRECISE_EMULATION
|
||||
void do_frsp (void);
|
||||
#endif
|
||||
void do_fctiw (void);
|
||||
void do_fctiwz (void);
|
||||
#if defined(TARGET_PPC64)
|
||||
|
||||
@@ -165,39 +165,6 @@ void OPPROTO glue(op_store_T1_crf_crf, REG) (void)
|
||||
RETURN();
|
||||
}
|
||||
|
||||
/* Floating point condition and status register moves */
|
||||
void OPPROTO glue(op_load_fpscr_T0_fpscr, REG) (void)
|
||||
{
|
||||
T0 = env->fpscr[REG];
|
||||
RETURN();
|
||||
}
|
||||
|
||||
#if REG == 0
|
||||
void OPPROTO glue(op_store_T0_fpscr_fpscr, REG) (void)
|
||||
{
|
||||
env->fpscr[REG] = (env->fpscr[REG] & 0x9) | (T0 & ~0x9);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_clear_fpscr_fpscr, REG) (void)
|
||||
{
|
||||
env->fpscr[REG] = (env->fpscr[REG] & 0x9);
|
||||
RETURN();
|
||||
}
|
||||
#else
|
||||
void OPPROTO glue(op_store_T0_fpscr_fpscr, REG) (void)
|
||||
{
|
||||
env->fpscr[REG] = T0;
|
||||
RETURN();
|
||||
}
|
||||
|
||||
void OPPROTO glue(op_clear_fpscr_fpscr, REG) (void)
|
||||
{
|
||||
env->fpscr[REG] = 0x0;
|
||||
RETURN();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* REG <= 7 */
|
||||
|
||||
/* floating point registers moves */
|
||||
|
||||
+173
-99
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user