MIPS patches 2015-09-18

Changes:
 * fixes for rdhwr, tlbwr, mtc0, recip.fmt, rsqrt.fmt and daui instructions
 * removal of MIPS_DEBUG code
 * use tcg_gen_extrh_i64_i32()
 * improve random tlb index generation in cpu_mips_get_random()
 * exception handling improvements to correctly restore icount
 -----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJV+/JQAAoJEFIRjjwLKdprNboH/3w5bd/PpHqG7HW8kZpf/Vhb
 DQwvbMDC20PulIieYl3+FQTu/G4X1Vio1MNmbb40g9E/ddoqnYnTfpZry8Fa6beZ
 ZgSdVZt0F0T9XS1BcAyQdpzdi9fefwWZrJUaHMvTTL68Qc8Y4R+4CAuSmsi0JsFZ
 euKQlEQCxFzB+hUSZoBYmo/gFVzJUkWXbl5qr82uWW7nlycv7uSe/bopTZvT30ad
 EbJvqs8Eok8FRIZP+Qr5wDejjOYpXTNaOocPV1rcXT9Ffb5ozeq6Qp2uXQJEjbJb
 kNX9IIEUVH4rE6w80xOVVDVXTypHYvRYWnLvsys/sF0tuVFWwDYRn2n37xU0bew=
 =VsAJ
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/lalrae/tags/mips-20150918' into staging

MIPS patches 2015-09-18

Changes:
* fixes for rdhwr, tlbwr, mtc0, recip.fmt, rsqrt.fmt and daui instructions
* removal of MIPS_DEBUG code
* use tcg_gen_extrh_i64_i32()
* improve random tlb index generation in cpu_mips_get_random()
* exception handling improvements to correctly restore icount

# gpg: Signature made Fri 18 Sep 2015 12:15:28 BST using RSA key ID 0B29DA6B
# gpg: Good signature from "Leon Alrae <leon.alrae@imgtec.com>"

* remotes/lalrae/tags/mips-20150918:
  target-mips: improve exception handling
  target-mips: correct MTC0 instruction on MIPS64
  target-mips: add missing restriction in DAUI instruction
  target-mips: fix corner case in TLBWR causing QEMU to hang
  pic32: use LCG algorithm for generated random index of TLBWR instruction
  target-mips: get rid of MIPS_DEBUG_SIGN_EXTENSIONS
  target-mips: get rid of MIPS_DEBUG
  target-mips: Fix RDHWR on CP0.Count
  target-mips: remove wrong checks for recip.fmt and rsqrt.fmt
  target-mips: Use tcg_gen_extrh_i64_i32

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-09-18 12:55:27 +01:00
commit 3bf1f5ec6a
6 changed files with 499 additions and 1071 deletions

View File

@ -30,13 +30,21 @@
/* XXX: do not use a global */ /* XXX: do not use a global */
uint32_t cpu_mips_get_random (CPUMIPSState *env) uint32_t cpu_mips_get_random (CPUMIPSState *env)
{ {
static uint32_t lfsr = 1; static uint32_t seed = 1;
static uint32_t prev_idx = 0; static uint32_t prev_idx = 0;
uint32_t idx; uint32_t idx;
uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired;
if (nb_rand_tlb == 1) {
return env->tlb->nb_tlb - 1;
}
/* Don't return same value twice, so get another value */ /* Don't return same value twice, so get another value */
do { do {
lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); /* Use a simple algorithm of Linear Congruential Generator
idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired; * from ISO/IEC 9899 standard. */
seed = 1103515245 * seed + 12345;
idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired;
} while (idx == prev_idx); } while (idx == prev_idx);
prev_idx = idx; prev_idx = idx;
return idx; return idx;

View File

@ -1049,4 +1049,28 @@ static inline void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val)
} }
#endif #endif
static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
uint32_t exception,
int error_code,
uintptr_t pc)
{
CPUState *cs = CPU(mips_env_get_cpu(env));
if (exception < EXCP_SC) {
qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n",
__func__, exception, error_code);
}
cs->exception_index = exception;
env->error_code = error_code;
cpu_loop_exit_restore(cs, pc);
}
static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
uint32_t exception,
uintptr_t pc)
{
do_raise_exception_err(env, exception, 0, pc);
}
#endif /* !defined (__MIPS_CPU_H__) */ #endif /* !defined (__MIPS_CPU_H__) */

View File

@ -1,5 +1,6 @@
DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int)
DEF_HELPER_2(raise_exception, noreturn, env, i32) DEF_HELPER_2(raise_exception, noreturn, env, i32)
DEF_HELPER_1(raise_exception_debug, noreturn, env)
DEF_HELPER_1(do_semihosting, void, env) DEF_HELPER_1(do_semihosting, void, env)

View File

@ -1352,7 +1352,7 @@ void helper_msa_ctcmsa(CPUMIPSState *env, target_ulong elm, uint32_t cd)
/* check exception */ /* check exception */
if ((GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED) if ((GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)
& GET_FP_CAUSE(env->active_tc.msacsr)) { & GET_FP_CAUSE(env->active_tc.msacsr)) {
helper_raise_exception(env, EXCP_MSAFPE); do_raise_exception(env, EXCP_MSAFPE, GETPC());
} }
break; break;
} }
@ -1505,14 +1505,14 @@ static inline void clear_msacsr_cause(CPUMIPSState *env)
SET_FP_CAUSE(env->active_tc.msacsr, 0); SET_FP_CAUSE(env->active_tc.msacsr, 0);
} }
static inline void check_msacsr_cause(CPUMIPSState *env) static inline void check_msacsr_cause(CPUMIPSState *env, uintptr_t retaddr)
{ {
if ((GET_FP_CAUSE(env->active_tc.msacsr) & if ((GET_FP_CAUSE(env->active_tc.msacsr) &
(GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)) == 0) { (GET_FP_ENABLE(env->active_tc.msacsr) | FP_UNIMPLEMENTED)) == 0) {
UPDATE_FP_FLAGS(env->active_tc.msacsr, UPDATE_FP_FLAGS(env->active_tc.msacsr,
GET_FP_CAUSE(env->active_tc.msacsr)); GET_FP_CAUSE(env->active_tc.msacsr));
} else { } else {
helper_raise_exception(env, EXCP_MSAFPE); do_raise_exception(env, EXCP_MSAFPE, retaddr);
} }
} }
@ -1851,7 +1851,8 @@ static inline int32 float64_to_q32(float64 a, float_status *status)
} while (0) } while (0)
static inline void compare_af(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_af(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -1873,13 +1874,14 @@ static inline void compare_af(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_un(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_un(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -1903,13 +1905,14 @@ static inline void compare_un(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_eq(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_eq(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -1931,13 +1934,14 @@ static inline void compare_eq(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_ueq(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_ueq(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -1959,13 +1963,14 @@ static inline void compare_ueq(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_lt(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_lt(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -1987,13 +1992,14 @@ static inline void compare_lt(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_ult(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_ult(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -2015,13 +2021,14 @@ static inline void compare_ult(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_le(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_le(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -2043,13 +2050,14 @@ static inline void compare_le(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_ule(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_ule(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -2071,13 +2079,14 @@ static inline void compare_ule(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_or(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_or(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -2099,13 +2108,14 @@ static inline void compare_or(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_une(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_une(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{ {
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -2127,13 +2137,15 @@ static inline void compare_une(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
static inline void compare_ne(CPUMIPSState *env, wr_t *pwd, wr_t *pws, static inline void compare_ne(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
wr_t *pwt, uint32_t df, int quiet) { wr_t *pwt, uint32_t df, int quiet,
uintptr_t retaddr)
{
wr_t wx, *pwx = &wx; wr_t wx, *pwx = &wx;
uint32_t i; uint32_t i;
@ -2154,7 +2166,7 @@ static inline void compare_ne(CPUMIPSState *env, wr_t *pwd, wr_t *pws,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, retaddr);
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2165,7 +2177,7 @@ void helper_msa_fcaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_af(env, pwd, pws, pwt, df, 1); compare_af(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fcun_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fcun_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2174,7 +2186,7 @@ void helper_msa_fcun_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_un(env, pwd, pws, pwt, df, 1); compare_un(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fceq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fceq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2183,7 +2195,7 @@ void helper_msa_fceq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_eq(env, pwd, pws, pwt, df, 1); compare_eq(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fcueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fcueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2192,7 +2204,7 @@ void helper_msa_fcueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_ueq(env, pwd, pws, pwt, df, 1); compare_ueq(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fclt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fclt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2201,7 +2213,7 @@ void helper_msa_fclt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_lt(env, pwd, pws, pwt, df, 1); compare_lt(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fcult_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fcult_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2210,7 +2222,7 @@ void helper_msa_fcult_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_ult(env, pwd, pws, pwt, df, 1); compare_ult(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fcle_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fcle_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2219,7 +2231,7 @@ void helper_msa_fcle_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_le(env, pwd, pws, pwt, df, 1); compare_le(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fcule_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fcule_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2228,7 +2240,7 @@ void helper_msa_fcule_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_ule(env, pwd, pws, pwt, df, 1); compare_ule(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fsaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2237,7 +2249,7 @@ void helper_msa_fsaf_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_af(env, pwd, pws, pwt, df, 0); compare_af(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fsun_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsun_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2246,7 +2258,7 @@ void helper_msa_fsun_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_un(env, pwd, pws, pwt, df, 0); compare_un(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fseq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fseq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2255,7 +2267,7 @@ void helper_msa_fseq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_eq(env, pwd, pws, pwt, df, 0); compare_eq(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fsueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2264,7 +2276,7 @@ void helper_msa_fsueq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_ueq(env, pwd, pws, pwt, df, 0); compare_ueq(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fslt_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fslt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2273,7 +2285,7 @@ void helper_msa_fslt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_lt(env, pwd, pws, pwt, df, 0); compare_lt(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fsult_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsult_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2282,7 +2294,7 @@ void helper_msa_fsult_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_ult(env, pwd, pws, pwt, df, 0); compare_ult(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fsle_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsle_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2291,7 +2303,7 @@ void helper_msa_fsle_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_le(env, pwd, pws, pwt, df, 0); compare_le(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fsule_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsule_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2300,7 +2312,7 @@ void helper_msa_fsule_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_ule(env, pwd, pws, pwt, df, 0); compare_ule(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fcor_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fcor_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2309,7 +2321,7 @@ void helper_msa_fcor_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_or(env, pwd, pws, pwt, df, 1); compare_or(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fcune_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fcune_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2318,7 +2330,7 @@ void helper_msa_fcune_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_une(env, pwd, pws, pwt, df, 1); compare_une(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fcne_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fcne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2327,7 +2339,7 @@ void helper_msa_fcne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_ne(env, pwd, pws, pwt, df, 1); compare_ne(env, pwd, pws, pwt, df, 1, GETPC());
} }
void helper_msa_fsor_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsor_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2336,7 +2348,7 @@ void helper_msa_fsor_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_or(env, pwd, pws, pwt, df, 0); compare_or(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fsune_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsune_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2345,7 +2357,7 @@ void helper_msa_fsune_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_une(env, pwd, pws, pwt, df, 0); compare_une(env, pwd, pws, pwt, df, 0, GETPC());
} }
void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd, void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
@ -2354,7 +2366,7 @@ void helper_msa_fsne_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
wr_t *pwd = &(env->active_fpu.fpr[wd].wr); wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
wr_t *pws = &(env->active_fpu.fpr[ws].wr); wr_t *pws = &(env->active_fpu.fpr[ws].wr);
wr_t *pwt = &(env->active_fpu.fpr[wt].wr); wr_t *pwt = &(env->active_fpu.fpr[wt].wr);
compare_ne(env, pwd, pws, pwt, df, 0); compare_ne(env, pwd, pws, pwt, df, 0, GETPC());
} }
#define float16_is_zero(ARG) 0 #define float16_is_zero(ARG) 0
@ -2404,7 +2416,7 @@ void helper_msa_fadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2434,7 +2446,7 @@ void helper_msa_fsub_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2464,7 +2476,7 @@ void helper_msa_fmul_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2495,7 +2507,7 @@ void helper_msa_fdiv_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2542,7 +2554,7 @@ void helper_msa_fmadd_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2577,7 +2589,7 @@ void helper_msa_fmsub_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2614,7 +2626,7 @@ void helper_msa_fexp2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2666,7 +2678,7 @@ void helper_msa_fexdo_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2712,7 +2724,7 @@ void helper_msa_ftq_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2791,7 +2803,7 @@ void helper_msa_fmin_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2822,7 +2834,7 @@ void helper_msa_fmin_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2865,7 +2877,7 @@ void helper_msa_fmax_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2896,7 +2908,7 @@ void helper_msa_fmax_a_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2958,7 +2970,7 @@ void helper_msa_ftrunc_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -2988,7 +3000,7 @@ void helper_msa_ftrunc_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3018,7 +3030,7 @@ void helper_msa_fsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3067,7 +3079,7 @@ void helper_msa_frsqrt_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3097,7 +3109,7 @@ void helper_msa_frcp_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3127,7 +3139,7 @@ void helper_msa_frint_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3181,7 +3193,7 @@ void helper_msa_flog2_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3216,7 +3228,7 @@ void helper_msa_fexupl_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3250,7 +3262,7 @@ void helper_msa_fexupr_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3331,7 +3343,7 @@ void helper_msa_ftint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3361,7 +3373,7 @@ void helper_msa_ftint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3397,7 +3409,7 @@ void helper_msa_ffint_s_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }
@ -3427,7 +3439,7 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd,
assert(0); assert(0);
} }
check_msacsr_cause(env); check_msacsr_cause(env, GETPC());
msa_move_v(pwd, pwx); msa_move_v(pwd, pwx);
} }

View File

@ -30,35 +30,6 @@ static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global);
/*****************************************************************************/ /*****************************************************************************/
/* Exceptions processing helpers */ /* Exceptions processing helpers */
static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
uint32_t exception,
int error_code,
uintptr_t pc)
{
CPUState *cs = CPU(mips_env_get_cpu(env));
if (exception < EXCP_SC) {
qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n",
__func__, exception, error_code);
}
cs->exception_index = exception;
env->error_code = error_code;
if (pc) {
/* now we have a real cpu fault */
cpu_restore_state(cs, pc);
}
cpu_loop_exit(cs);
}
static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
uint32_t exception,
uintptr_t pc)
{
do_raise_exception_err(env, exception, 0, pc);
}
void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception, void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
int error_code) int error_code)
{ {
@ -66,6 +37,16 @@ void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
} }
void helper_raise_exception(CPUMIPSState *env, uint32_t exception) void helper_raise_exception(CPUMIPSState *env, uint32_t exception)
{
do_raise_exception(env, exception, GETPC());
}
void helper_raise_exception_debug(CPUMIPSState *env)
{
do_raise_exception(env, EXCP_DEBUG, 0);
}
static void raise_exception(CPUMIPSState *env, uint32_t exception)
{ {
do_raise_exception(env, exception, 0); do_raise_exception(env, exception, 0);
} }
@ -73,21 +54,21 @@ void helper_raise_exception(CPUMIPSState *env, uint32_t exception)
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
#define HELPER_LD(name, insn, type) \ #define HELPER_LD(name, insn, type) \
static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \
int mem_idx) \ int mem_idx, uintptr_t retaddr) \
{ \ { \
return (type) cpu_##insn##_data(env, addr); \ return (type) cpu_##insn##_data_ra(env, addr, retaddr); \
} }
#else #else
#define HELPER_LD(name, insn, type) \ #define HELPER_LD(name, insn, type) \
static inline type do_##name(CPUMIPSState *env, target_ulong addr, \ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \
int mem_idx) \ int mem_idx, uintptr_t retaddr) \
{ \ { \
switch (mem_idx) \ switch (mem_idx) \
{ \ { \
case 0: return (type) cpu_##insn##_kernel(env, addr); break; \ case 0: return (type) cpu_##insn##_kernel_ra(env, addr, retaddr); \
case 1: return (type) cpu_##insn##_super(env, addr); break; \ case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \
default: \ default: \
case 2: return (type) cpu_##insn##_user(env, addr); break; \ case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \
} \ } \
} }
#endif #endif
@ -100,21 +81,21 @@ HELPER_LD(ld, ldq, int64_t)
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
#define HELPER_ST(name, insn, type) \ #define HELPER_ST(name, insn, type) \
static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \
type val, int mem_idx) \ type val, int mem_idx, uintptr_t retaddr) \
{ \ { \
cpu_##insn##_data(env, addr, val); \ cpu_##insn##_data_ra(env, addr, val, retaddr); \
} }
#else #else
#define HELPER_ST(name, insn, type) \ #define HELPER_ST(name, insn, type) \
static inline void do_##name(CPUMIPSState *env, target_ulong addr, \ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \
type val, int mem_idx) \ type val, int mem_idx, uintptr_t retaddr) \
{ \ { \
switch (mem_idx) \ switch (mem_idx) \
{ \ { \
case 0: cpu_##insn##_kernel(env, addr, val); break; \ case 0: cpu_##insn##_kernel_ra(env, addr, val, retaddr); break; \
case 1: cpu_##insn##_super(env, addr, val); break; \ case 1: cpu_##insn##_super_ra(env, addr, val, retaddr); break; \
default: \ default: \
case 2: cpu_##insn##_user(env, addr, val); break; \ case 2: cpu_##insn##_user_ra(env, addr, val, retaddr); break; \
} \ } \
} }
#endif #endif
@ -293,14 +274,15 @@ target_ulong helper_bitswap(target_ulong rt)
static inline hwaddr do_translate_address(CPUMIPSState *env, static inline hwaddr do_translate_address(CPUMIPSState *env,
target_ulong address, target_ulong address,
int rw) int rw, uintptr_t retaddr)
{ {
hwaddr lladdr; hwaddr lladdr;
CPUState *cs = CPU(mips_env_get_cpu(env));
lladdr = cpu_mips_translate_address(env, address, rw); lladdr = cpu_mips_translate_address(env, address, rw);
if (lladdr == -1LL) { if (lladdr == -1LL) {
cpu_loop_exit(CPU(mips_env_get_cpu(env))); cpu_loop_exit_restore(cs, retaddr);
} else { } else {
return lladdr; return lladdr;
} }
@ -311,10 +293,10 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx) \
{ \ { \
if (arg & almask) { \ if (arg & almask) { \
env->CP0_BadVAddr = arg; \ env->CP0_BadVAddr = arg; \
helper_raise_exception(env, EXCP_AdEL); \ do_raise_exception(env, EXCP_AdEL, GETPC()); \
} \ } \
env->lladdr = do_translate_address(env, arg, 0); \ env->lladdr = do_translate_address(env, arg, 0, GETPC()); \
env->llval = do_##insn(env, arg, mem_idx); \ env->llval = do_##insn(env, arg, mem_idx, GETPC()); \
return env->llval; \ return env->llval; \
} }
HELPER_LD_ATOMIC(ll, lw, 0x3) HELPER_LD_ATOMIC(ll, lw, 0x3)
@ -331,12 +313,12 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong arg1, \
\ \
if (arg2 & almask) { \ if (arg2 & almask) { \
env->CP0_BadVAddr = arg2; \ env->CP0_BadVAddr = arg2; \
helper_raise_exception(env, EXCP_AdES); \ do_raise_exception(env, EXCP_AdES, GETPC()); \
} \ } \
if (do_translate_address(env, arg2, 1) == env->lladdr) { \ if (do_translate_address(env, arg2, 1, GETPC()) == env->lladdr) { \
tmp = do_##ld_insn(env, arg2, mem_idx); \ tmp = do_##ld_insn(env, arg2, mem_idx, GETPC()); \
if (tmp == env->llval) { \ if (tmp == env->llval) { \
do_##st_insn(env, arg2, arg1, mem_idx); \ do_##st_insn(env, arg2, arg1, mem_idx, GETPC()); \
return 1; \ return 1; \
} \ } \
} \ } \
@ -360,31 +342,43 @@ HELPER_ST_ATOMIC(scd, ld, sd, 0x7)
void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
int mem_idx) int mem_idx)
{ {
do_sb(env, arg2, (uint8_t)(arg1 >> 24), mem_idx); do_sb(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC());
if (GET_LMASK(arg2) <= 2) if (GET_LMASK(arg2) <= 2) {
do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx); do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx,
GETPC());
}
if (GET_LMASK(arg2) <= 1) if (GET_LMASK(arg2) <= 1) {
do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx); do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx,
GETPC());
}
if (GET_LMASK(arg2) == 0) if (GET_LMASK(arg2) == 0) {
do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx); do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx,
GETPC());
}
} }
void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
int mem_idx) int mem_idx)
{ {
do_sb(env, arg2, (uint8_t)arg1, mem_idx); do_sb(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
if (GET_LMASK(arg2) >= 1) if (GET_LMASK(arg2) >= 1) {
do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx); do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx,
GETPC());
}
if (GET_LMASK(arg2) >= 2) if (GET_LMASK(arg2) >= 2) {
do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx); do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx,
GETPC());
}
if (GET_LMASK(arg2) == 3) if (GET_LMASK(arg2) == 3) {
do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx); do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx,
GETPC());
}
} }
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
@ -400,55 +394,83 @@ void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
int mem_idx) int mem_idx)
{ {
do_sb(env, arg2, (uint8_t)(arg1 >> 56), mem_idx); do_sb(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC());
if (GET_LMASK64(arg2) <= 6) if (GET_LMASK64(arg2) <= 6) {
do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx); do_sb(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) <= 5) if (GET_LMASK64(arg2) <= 5) {
do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx); do_sb(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) <= 4) if (GET_LMASK64(arg2) <= 4) {
do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx); do_sb(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) <= 3) if (GET_LMASK64(arg2) <= 3) {
do_sb(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx); do_sb(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) <= 2) if (GET_LMASK64(arg2) <= 2) {
do_sb(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx); do_sb(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) <= 1) if (GET_LMASK64(arg2) <= 1) {
do_sb(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx); do_sb(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) <= 0) if (GET_LMASK64(arg2) <= 0) {
do_sb(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx); do_sb(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx,
GETPC());
}
} }
void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2,
int mem_idx) int mem_idx)
{ {
do_sb(env, arg2, (uint8_t)arg1, mem_idx); do_sb(env, arg2, (uint8_t)arg1, mem_idx, GETPC());
if (GET_LMASK64(arg2) >= 1) if (GET_LMASK64(arg2) >= 1) {
do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx); do_sb(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) >= 2) if (GET_LMASK64(arg2) >= 2) {
do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx); do_sb(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) >= 3) if (GET_LMASK64(arg2) >= 3) {
do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx); do_sb(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) >= 4) if (GET_LMASK64(arg2) >= 4) {
do_sb(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx); do_sb(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) >= 5) if (GET_LMASK64(arg2) >= 5) {
do_sb(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx); do_sb(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) >= 6) if (GET_LMASK64(arg2) >= 6) {
do_sb(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx); do_sb(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx,
GETPC());
}
if (GET_LMASK64(arg2) == 7) if (GET_LMASK64(arg2) == 7) {
do_sb(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx); do_sb(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx,
GETPC());
}
} }
#endif /* TARGET_MIPS64 */ #endif /* TARGET_MIPS64 */
@ -465,13 +487,14 @@ void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
for (i = 0; i < base_reglist; i++) { for (i = 0; i < base_reglist; i++) {
env->active_tc.gpr[multiple_regs[i]] = env->active_tc.gpr[multiple_regs[i]] =
(target_long)do_lw(env, addr, mem_idx); (target_long)do_lw(env, addr, mem_idx, GETPC());
addr += 4; addr += 4;
} }
} }
if (do_r31) { if (do_r31) {
env->active_tc.gpr[31] = (target_long)do_lw(env, addr, mem_idx); env->active_tc.gpr[31] = (target_long)do_lw(env, addr, mem_idx,
GETPC());
} }
} }
@ -485,13 +508,14 @@ void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
target_ulong i; target_ulong i;
for (i = 0; i < base_reglist; i++) { for (i = 0; i < base_reglist; i++) {
do_sw(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx); do_sw(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx,
GETPC());
addr += 4; addr += 4;
} }
} }
if (do_r31) { if (do_r31) {
do_sw(env, addr, env->active_tc.gpr[31], mem_idx); do_sw(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
} }
} }
@ -506,13 +530,14 @@ void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
target_ulong i; target_ulong i;
for (i = 0; i < base_reglist; i++) { for (i = 0; i < base_reglist; i++) {
env->active_tc.gpr[multiple_regs[i]] = do_ld(env, addr, mem_idx); env->active_tc.gpr[multiple_regs[i]] = do_ld(env, addr, mem_idx,
GETPC());
addr += 8; addr += 8;
} }
} }
if (do_r31) { if (do_r31) {
env->active_tc.gpr[31] = do_ld(env, addr, mem_idx); env->active_tc.gpr[31] = do_ld(env, addr, mem_idx, GETPC());
} }
} }
@ -526,13 +551,14 @@ void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist,
target_ulong i; target_ulong i;
for (i = 0; i < base_reglist; i++) { for (i = 0; i < base_reglist; i++) {
do_sd(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx); do_sd(env, addr, env->active_tc.gpr[multiple_regs[i]], mem_idx,
GETPC());
addr += 8; addr += 8;
} }
} }
if (do_r31) { if (do_r31) {
do_sd(env, addr, env->active_tc.gpr[31], mem_idx); do_sd(env, addr, env->active_tc.gpr[31], mem_idx, GETPC());
} }
} }
#endif #endif
@ -1792,13 +1818,13 @@ target_ulong helper_yield(CPUMIPSState *env, target_ulong arg)
env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) { env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT; env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
helper_raise_exception(env, EXCP_THREAD); do_raise_exception(env, EXCP_THREAD, GETPC());
} }
} }
} else if (arg1 == 0) { } else if (arg1 == 0) {
if (0 /* TODO: TC underflow */) { if (0 /* TODO: TC underflow */) {
env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
helper_raise_exception(env, EXCP_THREAD); do_raise_exception(env, EXCP_THREAD, GETPC());
} else { } else {
// TODO: Deallocate TC // TODO: Deallocate TC
} }
@ -1806,7 +1832,7 @@ target_ulong helper_yield(CPUMIPSState *env, target_ulong arg)
/* Yield qualifier inputs not implemented. */ /* Yield qualifier inputs not implemented. */
env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT; env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
helper_raise_exception(env, EXCP_THREAD); do_raise_exception(env, EXCP_THREAD, GETPC());
} }
return env->CP0_YQMask; return env->CP0_YQMask;
} }
@ -2165,7 +2191,7 @@ target_ulong helper_rdhwr_cpunum(CPUMIPSState *env)
(env->CP0_HWREna & (1 << 0))) (env->CP0_HWREna & (1 << 0)))
return env->CP0_EBase & 0x3ff; return env->CP0_EBase & 0x3ff;
else else
helper_raise_exception(env, EXCP_RI); do_raise_exception(env, EXCP_RI, GETPC());
return 0; return 0;
} }
@ -2176,7 +2202,7 @@ target_ulong helper_rdhwr_synci_step(CPUMIPSState *env)
(env->CP0_HWREna & (1 << 1))) (env->CP0_HWREna & (1 << 1)))
return env->SYNCI_Step; return env->SYNCI_Step;
else else
helper_raise_exception(env, EXCP_RI); do_raise_exception(env, EXCP_RI, GETPC());
return 0; return 0;
} }
@ -2184,10 +2210,15 @@ target_ulong helper_rdhwr_synci_step(CPUMIPSState *env)
target_ulong helper_rdhwr_cc(CPUMIPSState *env) target_ulong helper_rdhwr_cc(CPUMIPSState *env)
{ {
if ((env->hflags & MIPS_HFLAG_CP0) || if ((env->hflags & MIPS_HFLAG_CP0) ||
(env->CP0_HWREna & (1 << 2))) (env->CP0_HWREna & (1 << 2))) {
#ifdef CONFIG_USER_ONLY
return env->CP0_Count; return env->CP0_Count;
else #else
helper_raise_exception(env, EXCP_RI); return (int32_t)cpu_mips_get_count(env);
#endif
} else {
do_raise_exception(env, EXCP_RI, GETPC());
}
return 0; return 0;
} }
@ -2198,7 +2229,7 @@ target_ulong helper_rdhwr_ccres(CPUMIPSState *env)
(env->CP0_HWREna & (1 << 3))) (env->CP0_HWREna & (1 << 3)))
return env->CCRes; return env->CCRes;
else else
helper_raise_exception(env, EXCP_RI); do_raise_exception(env, EXCP_RI, GETPC());
return 0; return 0;
} }
@ -2235,7 +2266,9 @@ void helper_wait(CPUMIPSState *env)
cs->halted = 1; cs->halted = 1;
cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
helper_raise_exception(env, EXCP_HLT); /* Last instruction in the block, PC was updated before
- no need to recover PC and icount */
raise_exception(env, EXCP_HLT);
} }
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)
@ -2296,9 +2329,9 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr,
} }
if (is_exec) { if (is_exec) {
helper_raise_exception(env, EXCP_IBE); raise_exception(env, EXCP_IBE);
} else { } else {
helper_raise_exception(env, EXCP_DBE); raise_exception(env, EXCP_DBE);
} }
} }
#endif /* !CONFIG_USER_ONLY */ #endif /* !CONFIG_USER_ONLY */
@ -2333,7 +2366,7 @@ target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg)
arg1 = (int32_t) arg1 = (int32_t)
((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR); ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR);
} else { } else {
helper_raise_exception(env, EXCP_RI); do_raise_exception(env, EXCP_RI, GETPC());
} }
} }
break; break;
@ -2376,7 +2409,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
env->CP0_Status &= ~(1 << CP0St_FR); env->CP0_Status &= ~(1 << CP0St_FR);
compute_hflags(env); compute_hflags(env);
} else { } else {
helper_raise_exception(env, EXCP_RI); do_raise_exception(env, EXCP_RI, GETPC());
} }
break; break;
case 4: case 4:
@ -2388,7 +2421,7 @@ void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt)
env->CP0_Status |= (1 << CP0St_FR); env->CP0_Status |= (1 << CP0St_FR);
compute_hflags(env); compute_hflags(env);
} else { } else {
helper_raise_exception(env, EXCP_RI); do_raise_exception(env, EXCP_RI, GETPC());
} }
break; break;
case 5: case 5:

File diff suppressed because it is too large Load Diff