/*****************************************************************************/
/* Exceptions processing helpers */
-void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
- int error_code)
+static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
+ uint32_t exception,
+ int error_code,
+ uintptr_t pc)
{
+ TranslationBlock *tb;
#if 1
if (exception < 0x100)
qemu_log("%s: %d %d\n", __func__, exception, error_code);
#endif
env->exception_index = exception;
env->error_code = error_code;
+
+ if (pc) {
+ /* now we have a real cpu fault */
+ tb = tb_find_pc(pc);
+ if (tb) {
+ /* the PC is inside the translated code. It means that we have
+ a virtual CPU fault */
+ cpu_restore_state(tb, env, pc);
+ }
+ }
+
cpu_loop_exit(env);
}
-void helper_raise_exception(CPUMIPSState *env, uint32_t exception)
+static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
+ uint32_t exception,
+ uintptr_t pc)
{
- helper_raise_exception_err(env, exception, 0);
+ do_raise_exception_err(env, exception, 0, pc);
}
-#if !defined(CONFIG_USER_ONLY)
-static void do_restore_state(CPUMIPSState *env, uintptr_t pc)
+void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
+ int error_code)
{
- TranslationBlock *tb;
+ do_raise_exception_err(env, exception, error_code, 0);
+}
- tb = tb_find_pc (pc);
- if (tb) {
- cpu_restore_state(tb, env, pc);
- }
+void helper_raise_exception(CPUMIPSState *env, uint32_t exception)
+{
+ do_raise_exception(env, exception, 0);
}
-#endif
#if defined(CONFIG_USER_ONLY)
#define HELPER_LD(name, insn, type) \
int is_write, int is_user, uintptr_t retaddr)
{
env->CP0_BadVAddr = addr;
- do_restore_state(env, retaddr);
- helper_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL);
+ do_raise_exception(env, (is_write == 1) ? EXCP_AdES : EXCP_AdEL, retaddr);
}
void tlb_fill(CPUMIPSState *env, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
- TranslationBlock *tb;
int ret;
ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (ret) {
- if (retaddr) {
- /* now we have a real cpu fault */
- tb = tb_find_pc(retaddr);
- if (tb) {
- /* the PC is inside the translated code. It means that we have
- a virtual CPU fault */
- cpu_restore_state(tb, env, retaddr);
- }
- }
- helper_raise_exception_err(env, env->exception_index, env->error_code);
+ do_raise_exception_err(env, env->exception_index,
+ env->error_code, retaddr);
}
}
RESTORE_FLUSH_MODE;
set_float_exception_flags(0, &env->active_fpu.fp_status);
if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
- helper_raise_exception(env, EXCP_FPE);
+ do_raise_exception(env, EXCP_FPE, GETPC());
}
static inline int ieee_ex_to_mips(int xcpt)
return ret;
}
-static inline void update_fcr31(CPUMIPSState *env)
+static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc)
{
int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
set_float_exception_flags(0, &env->active_fpu.fp_status);
if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) {
- helper_raise_exception(env, EXCP_FPE);
+ do_raise_exception(env, EXCP_FPE, pc);
} else {
UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
}
uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0)
{
fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt0;
}
uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0)
{
fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst0;
}
uint64_t fdt2;
fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
uint64_t fdt2;
fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
uint64_t fdt2;
fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return ((uint64_t)fsth2 << 32) | fst2;
}
}
set_float_exception_flags(excp | excph, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return ((uint64_t)wth2 << 32) | wt2;
}
uint32_t fst2;
fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
uint32_t fst2;
fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
uint32_t fst2;
fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
uint32_t wt2;
wt2 = wt0;
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
uint32_t wt2;
wt2 = wth0;
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
uint32_t wt2;
wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
if (get_float_exception_flags(&env->active_fpu.fp_status)
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
dt2 = FP_TO_INT64_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return dt2;
}
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
& (float_flag_invalid | float_flag_overflow)) {
wt2 = FP_TO_INT32_OVERFLOW;
}
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return wt2;
}
uint64_t fdt2;
fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
uint32_t fst2;
fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
uint64_t fdt2;
fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
uint32_t fst2;
fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return ((uint64_t)fsth2 << 32) | fst2;
}
fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status);
fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return ((uint64_t)fsth2 << 32) | fst2;
}
uint64_t dt2; \
\
dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status); \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
return dt2; \
} \
\
uint32_t wt2; \
\
wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
return wt2; \
} \
\
\
wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status); \
wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status); \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
return ((uint64_t)wth2 << 32) | wt2; \
}
{ \
fdt0 = float64_muladd(fdt0, fdt1, fdt2, type, \
&env->active_fpu.fp_status); \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
return fdt0; \
} \
\
{ \
fst0 = float32_muladd(fst0, fst1, fst2, type, \
&env->active_fpu.fp_status); \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
return fst0; \
} \
\
&env->active_fpu.fp_status); \
fsth0 = float32_muladd(fsth0, fsth1, fsth2, type, \
&env->active_fpu.fp_status); \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
return ((uint64_t)fsth0 << 32) | fst0; \
}
FLOAT_FMA(madd, 0)
{
fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
fdt2 = float64_chs(float64_sub(fdt2, float64_one, &env->active_fpu.fp_status));
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
{
fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status));
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
fst2 = float32_chs(float32_sub(fst2, float32_one, &env->active_fpu.fp_status));
fsth2 = float32_chs(float32_sub(fsth2, float32_one, &env->active_fpu.fp_status));
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return ((uint64_t)fsth2 << 32) | fst2;
}
fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status);
fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fdt2;
}
fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status);
fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return fst2;
}
fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status);
fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return ((uint64_t)fsth2 << 32) | fst2;
}
fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return ((uint64_t)fsth2 << 32) | fst2;
}
fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
- update_fcr31(env);
+ update_fcr31(env, GETPC());
return ((uint64_t)fsth2 << 32) | fst2;
}
{ \
int c; \
c = cond; \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
if (c) \
SET_FP_COND(cc, env->active_fpu); \
else \
fdt0 = float64_abs(fdt0); \
fdt1 = float64_abs(fdt1); \
c = cond; \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
if (c) \
SET_FP_COND(cc, env->active_fpu); \
else \
{ \
int c; \
c = cond; \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
if (c) \
SET_FP_COND(cc, env->active_fpu); \
else \
fst0 = float32_abs(fst0); \
fst1 = float32_abs(fst1); \
c = cond; \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
if (c) \
SET_FP_COND(cc, env->active_fpu); \
else \
fsth1 = fdt1 >> 32; \
cl = condl; \
ch = condh; \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
if (cl) \
SET_FP_COND(cc, env->active_fpu); \
else \
fsth1 = float32_abs(fdt1 >> 32); \
cl = condl; \
ch = condh; \
- update_fcr31(env); \
+ update_fcr31(env, GETPC()); \
if (cl) \
SET_FP_COND(cc, env->active_fpu); \
else \