mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 00:33:55 -06:00
target/mips: fpu: Refactor conversion from ieee to mips exception flags
The original coversion function is used for regular and MSA floating point instructions handling. Since there are some nuanced differences between regular and MSA floating point exception handling, provide two instances of the conversion function, rather than just a single common one. Inline both instances of this function instances for the sake of performance. Improve variable naming in surrounding code for clarity. Reviewed-by: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> Signed-off-by: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> Message-Id: <20200518200920.17344-17-aleksandar.qemu.devel@gmail.com>
This commit is contained in:
parent
485cd2e4ce
commit
9579f78168
3 changed files with 82 additions and 51 deletions
|
@ -5419,54 +5419,81 @@ static inline void check_msacsr_cause(CPUMIPSState *env, uintptr_t retaddr)
|
|||
#define CLEAR_IS_INEXACT 2
|
||||
#define RECIPROCAL_INEXACT 4
|
||||
|
||||
|
||||
static inline int ieee_to_mips_xcpt_msa(int ieee_xcpt)
|
||||
{
|
||||
int mips_xcpt = 0;
|
||||
|
||||
if (ieee_xcpt & float_flag_invalid) {
|
||||
mips_xcpt |= FP_INVALID;
|
||||
}
|
||||
if (ieee_xcpt & float_flag_overflow) {
|
||||
mips_xcpt |= FP_OVERFLOW;
|
||||
}
|
||||
if (ieee_xcpt & float_flag_underflow) {
|
||||
mips_xcpt |= FP_UNDERFLOW;
|
||||
}
|
||||
if (ieee_xcpt & float_flag_divbyzero) {
|
||||
mips_xcpt |= FP_DIV0;
|
||||
}
|
||||
if (ieee_xcpt & float_flag_inexact) {
|
||||
mips_xcpt |= FP_INEXACT;
|
||||
}
|
||||
|
||||
return mips_xcpt;
|
||||
}
|
||||
|
||||
static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
|
||||
{
|
||||
int ieee_ex;
|
||||
|
||||
int c;
|
||||
int ieee_exception_flags;
|
||||
int mips_exception_flags = 0;
|
||||
int cause;
|
||||
int enable;
|
||||
|
||||
ieee_ex = get_float_exception_flags(&env->active_tc.msa_fp_status);
|
||||
ieee_exception_flags = get_float_exception_flags(
|
||||
&env->active_tc.msa_fp_status);
|
||||
|
||||
/* QEMU softfloat does not signal all underflow cases */
|
||||
if (denormal) {
|
||||
ieee_ex |= float_flag_underflow;
|
||||
ieee_exception_flags |= float_flag_underflow;
|
||||
}
|
||||
if (ieee_exception_flags) {
|
||||
mips_exception_flags = ieee_to_mips_xcpt_msa(ieee_exception_flags);
|
||||
}
|
||||
|
||||
c = ieee_ex_to_mips(ieee_ex);
|
||||
enable = GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED;
|
||||
|
||||
/* Set Inexact (I) when flushing inputs to zero */
|
||||
if ((ieee_ex & float_flag_input_denormal) &&
|
||||
if ((ieee_exception_flags & float_flag_input_denormal) &&
|
||||
(env->active_tc.msacsr & MSACSR_FS_MASK) != 0) {
|
||||
if (action & CLEAR_IS_INEXACT) {
|
||||
c &= ~FP_INEXACT;
|
||||
mips_exception_flags &= ~FP_INEXACT;
|
||||
} else {
|
||||
c |= FP_INEXACT;
|
||||
mips_exception_flags |= FP_INEXACT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Inexact (I) and Underflow (U) when flushing outputs to zero */
|
||||
if ((ieee_ex & float_flag_output_denormal) &&
|
||||
if ((ieee_exception_flags & float_flag_output_denormal) &&
|
||||
(env->active_tc.msacsr & MSACSR_FS_MASK) != 0) {
|
||||
c |= FP_INEXACT;
|
||||
mips_exception_flags |= FP_INEXACT;
|
||||
if (action & CLEAR_FS_UNDERFLOW) {
|
||||
c &= ~FP_UNDERFLOW;
|
||||
mips_exception_flags &= ~FP_UNDERFLOW;
|
||||
} else {
|
||||
c |= FP_UNDERFLOW;
|
||||
mips_exception_flags |= FP_UNDERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Inexact (I) when Overflow (O) is not enabled */
|
||||
if ((c & FP_OVERFLOW) != 0 && (enable & FP_OVERFLOW) == 0) {
|
||||
c |= FP_INEXACT;
|
||||
if ((mips_exception_flags & FP_OVERFLOW) != 0 &&
|
||||
(enable & FP_OVERFLOW) == 0) {
|
||||
mips_exception_flags |= FP_INEXACT;
|
||||
}
|
||||
|
||||
/* Clear Exact Underflow when Underflow (U) is not enabled */
|
||||
if ((c & FP_UNDERFLOW) != 0 && (enable & FP_UNDERFLOW) == 0 &&
|
||||
(c & FP_INEXACT) == 0) {
|
||||
c &= ~FP_UNDERFLOW;
|
||||
if ((mips_exception_flags & FP_UNDERFLOW) != 0 &&
|
||||
(enable & FP_UNDERFLOW) == 0 &&
|
||||
(mips_exception_flags & FP_INEXACT) == 0) {
|
||||
mips_exception_flags &= ~FP_UNDERFLOW;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5474,11 +5501,11 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
|
|||
* divide by zero
|
||||
*/
|
||||
if ((action & RECIPROCAL_INEXACT) &&
|
||||
(c & (FP_INVALID | FP_DIV0)) == 0) {
|
||||
c = FP_INEXACT;
|
||||
(mips_exception_flags & (FP_INVALID | FP_DIV0)) == 0) {
|
||||
mips_exception_flags = FP_INEXACT;
|
||||
}
|
||||
|
||||
cause = c & enable; /* all current enabled exceptions */
|
||||
cause = mips_exception_flags & enable; /* all current enabled exceptions */
|
||||
|
||||
if (cause == 0) {
|
||||
/*
|
||||
|
@ -5486,7 +5513,7 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
|
|||
* with all current exceptions
|
||||
*/
|
||||
SET_FP_CAUSE(env->active_tc.msacsr,
|
||||
(GET_FP_CAUSE(env->active_tc.msacsr) | c));
|
||||
(GET_FP_CAUSE(env->active_tc.msacsr) | mips_exception_flags));
|
||||
} else {
|
||||
/* Current exceptions are enabled */
|
||||
if ((env->active_tc.msacsr & MSACSR_NX_MASK) == 0) {
|
||||
|
@ -5495,11 +5522,11 @@ static inline int update_msacsr(CPUMIPSState *env, int action, int denormal)
|
|||
* with all enabled exceptions
|
||||
*/
|
||||
SET_FP_CAUSE(env->active_tc.msacsr,
|
||||
(GET_FP_CAUSE(env->active_tc.msacsr) | c));
|
||||
(GET_FP_CAUSE(env->active_tc.msacsr) | mips_exception_flags));
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
return mips_exception_flags;
|
||||
}
|
||||
|
||||
static inline int get_enabled_exceptions(const CPUMIPSState *env, int c)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue