@@ -210,11 +210,6 @@ DEF_HELPER_1(tlbp, void, env)
DEF_HELPER_1(tlbr, void, env)
DEF_HELPER_1(tlbinv, void, env)
DEF_HELPER_1(tlbinvf, void, env)
-DEF_HELPER_1(di, tl, env)
-DEF_HELPER_1(ei, tl, env)
-DEF_HELPER_1(eret, void, env)
-DEF_HELPER_1(eretnc, void, env)
-DEF_HELPER_1(deret, void, env)
DEF_HELPER_3(ginvt, void, env, tl, i32)
#endif /* !CONFIG_USER_ONLY */
DEF_HELPER_1(rdhwr_cpunum, tl, env)
@@ -10,6 +10,7 @@
#ifndef MIPS_TCG_INTERNAL_H
#define MIPS_TCG_INTERNAL_H
+#include "tcg/tcg.h"
#include "hw/core/cpu.h"
#include "cpu.h"
@@ -27,6 +28,8 @@ void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra);
uint32_t cpu_mips_get_random(CPUMIPSState *env);
+bool mips_io_recompile_replay_branch(CPUState *cs, const TranslationBlock *tb);
+
hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address,
MMUAccessType access_type);
void cpu_mips_tlb_flush(CPUMIPSState *env);
@@ -166,3 +166,10 @@ DEF_HELPER_1(evpe, tl, env)
/* R6 Multi-threading */
DEF_HELPER_1(dvp, tl, env)
DEF_HELPER_1(evp, tl, env)
+
+/* Special */
+DEF_HELPER_1(di, tl, env)
+DEF_HELPER_1(ei, tl, env)
+DEF_HELPER_1(eret, void, env)
+DEF_HELPER_1(eretnc, void, env)
+DEF_HELPER_1(deret, void, env)
@@ -352,23 +352,6 @@ static void mips_cpu_synchronize_from_tb(CPUState *cs,
env->hflags &= ~MIPS_HFLAG_BMASK;
env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
}
-
-# ifndef CONFIG_USER_ONLY
-static bool mips_io_recompile_replay_branch(CPUState *cs,
- const TranslationBlock *tb)
-{
- MIPSCPU *cpu = MIPS_CPU(cs);
- CPUMIPSState *env = &cpu->env;
-
- if ((env->hflags & MIPS_HFLAG_BMASK) != 0
- && env->active_tc.PC != tb->pc) {
- env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
- env->hflags &= ~MIPS_HFLAG_BMASK;
- return true;
- }
- return false;
-}
-# endif /* !CONFIG_USER_ONLY */
#endif /* CONFIG_TCG */
static bool mips_cpu_has_work(CPUState *cs)
@@ -656,116 +656,6 @@ void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type)
}
}
-/* Specials */
-target_ulong helper_di(CPUMIPSState *env)
-{
- target_ulong t0 = env->CP0_Status;
-
- env->CP0_Status = t0 & ~(1 << CP0St_IE);
- return t0;
-}
-
-target_ulong helper_ei(CPUMIPSState *env)
-{
- target_ulong t0 = env->CP0_Status;
-
- env->CP0_Status = t0 | (1 << CP0St_IE);
- return t0;
-}
-
-static void debug_pre_eret(CPUMIPSState *env)
-{
- if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
- qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
- env->active_tc.PC, env->CP0_EPC);
- if (env->CP0_Status & (1 << CP0St_ERL)) {
- qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
- }
- if (env->hflags & MIPS_HFLAG_DM) {
- qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
- }
- qemu_log("\n");
- }
-}
-
-static void debug_post_eret(CPUMIPSState *env)
-{
- if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
- qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
- env->active_tc.PC, env->CP0_EPC);
- if (env->CP0_Status & (1 << CP0St_ERL)) {
- qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
- }
- if (env->hflags & MIPS_HFLAG_DM) {
- qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
- }
- switch (cpu_mmu_index(env, false)) {
- case 3:
- qemu_log(", ERL\n");
- break;
- case MIPS_HFLAG_UM:
- qemu_log(", UM\n");
- break;
- case MIPS_HFLAG_SM:
- qemu_log(", SM\n");
- break;
- case MIPS_HFLAG_KM:
- qemu_log("\n");
- break;
- default:
- cpu_abort(env_cpu(env), "Invalid MMU mode!\n");
- break;
- }
- }
-}
-
-static void set_pc(CPUMIPSState *env, target_ulong error_pc)
-{
- env->active_tc.PC = error_pc & ~(target_ulong)1;
- if (error_pc & 1) {
- env->hflags |= MIPS_HFLAG_M16;
- } else {
- env->hflags &= ~(MIPS_HFLAG_M16);
- }
-}
-
-static inline void exception_return(CPUMIPSState *env)
-{
- debug_pre_eret(env);
- if (env->CP0_Status & (1 << CP0St_ERL)) {
- set_pc(env, env->CP0_ErrorEPC);
- env->CP0_Status &= ~(1 << CP0St_ERL);
- } else {
- set_pc(env, env->CP0_EPC);
- env->CP0_Status &= ~(1 << CP0St_EXL);
- }
- compute_hflags(env);
- debug_post_eret(env);
-}
-
-void helper_eret(CPUMIPSState *env)
-{
- exception_return(env);
- env->CP0_LLAddr = 1;
- env->lladdr = 1;
-}
-
-void helper_eretnc(CPUMIPSState *env)
-{
- exception_return(env);
-}
-
-void helper_deret(CPUMIPSState *env)
-{
- debug_pre_eret(env);
-
- env->hflags &= ~MIPS_HFLAG_DM;
- compute_hflags(env);
-
- set_pc(env, env->CP0_DEPC);
-
- debug_post_eret(env);
-}
#endif /* !CONFIG_USER_ONLY */
static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc)
new file mode 100644
@@ -0,0 +1,150 @@
+/*
+ * QEMU MIPS emulation: Special opcode helpers
+ *
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "internal.h"
+
+/* Specials */
+target_ulong helper_di(CPUMIPSState *env)
+{
+ target_ulong t0 = env->CP0_Status;
+
+ env->CP0_Status = t0 & ~(1 << CP0St_IE);
+ return t0;
+}
+
+target_ulong helper_ei(CPUMIPSState *env)
+{
+ target_ulong t0 = env->CP0_Status;
+
+ env->CP0_Status = t0 | (1 << CP0St_IE);
+ return t0;
+}
+
+static void debug_pre_eret(CPUMIPSState *env)
+{
+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
+ qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
+ env->active_tc.PC, env->CP0_EPC);
+ if (env->CP0_Status & (1 << CP0St_ERL)) {
+ qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
+ }
+ if (env->hflags & MIPS_HFLAG_DM) {
+ qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
+ }
+ qemu_log("\n");
+ }
+}
+
+static void debug_post_eret(CPUMIPSState *env)
+{
+ if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
+ qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
+ env->active_tc.PC, env->CP0_EPC);
+ if (env->CP0_Status & (1 << CP0St_ERL)) {
+ qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
+ }
+ if (env->hflags & MIPS_HFLAG_DM) {
+ qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
+ }
+ switch (cpu_mmu_index(env, false)) {
+ case 3:
+ qemu_log(", ERL\n");
+ break;
+ case MIPS_HFLAG_UM:
+ qemu_log(", UM\n");
+ break;
+ case MIPS_HFLAG_SM:
+ qemu_log(", SM\n");
+ break;
+ case MIPS_HFLAG_KM:
+ qemu_log("\n");
+ break;
+ default:
+ cpu_abort(env_cpu(env), "Invalid MMU mode!\n");
+ break;
+ }
+ }
+}
+
+static void set_pc(CPUMIPSState *env, target_ulong error_pc)
+{
+ env->active_tc.PC = error_pc & ~(target_ulong)1;
+ if (error_pc & 1) {
+ env->hflags |= MIPS_HFLAG_M16;
+ } else {
+ env->hflags &= ~(MIPS_HFLAG_M16);
+ }
+}
+
+bool mips_io_recompile_replay_branch(CPUState *cs, const TranslationBlock *tb)
+{
+ MIPSCPU *cpu = MIPS_CPU(cs);
+ CPUMIPSState *env = &cpu->env;
+
+ if ((env->hflags & MIPS_HFLAG_BMASK) != 0
+ && env->active_tc.PC != tb->pc) {
+ env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
+ env->hflags &= ~MIPS_HFLAG_BMASK;
+ return true;
+ }
+ return false;
+}
+
+static inline void exception_return(CPUMIPSState *env)
+{
+ debug_pre_eret(env);
+ if (env->CP0_Status & (1 << CP0St_ERL)) {
+ set_pc(env, env->CP0_ErrorEPC);
+ env->CP0_Status &= ~(1 << CP0St_ERL);
+ } else {
+ set_pc(env, env->CP0_EPC);
+ env->CP0_Status &= ~(1 << CP0St_EXL);
+ }
+ compute_hflags(env);
+ debug_post_eret(env);
+}
+
+void helper_eret(CPUMIPSState *env)
+{
+ exception_return(env);
+ env->CP0_LLAddr = 1;
+ env->lladdr = 1;
+}
+
+void helper_eretnc(CPUMIPSState *env)
+{
+ exception_return(env);
+}
+
+void helper_deret(CPUMIPSState *env)
+{
+ debug_pre_eret(env);
+
+ env->hflags &= ~MIPS_HFLAG_DM;
+ compute_hflags(env);
+
+ set_pc(env, env->CP0_DEPC);
+
+ debug_post_eret(env);
+}
@@ -1,5 +1,6 @@
mips_softmmu_ss.add(files(
'cp0_helper.c',
'mips-semi.c',
+ 'special_helper.c',
'tlb_helper.c',
))
Move the Special opcodes helpers to tcg/sysemu/special_helper.c. Since mips_io_recompile_replay_branch() is set as CPUClass::io_recompile_replay_branch handler in cpu.c, we need to declare its prototype in "tcg-internal.h". Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> --- target/mips/helper.h | 5 - target/mips/tcg/tcg-internal.h | 3 + target/mips/tcg/sysemu_helper.h.inc | 7 ++ target/mips/cpu.c | 17 --- target/mips/op_helper.c | 110 ----------------- target/mips/tcg/sysemu/special_helper.c | 150 ++++++++++++++++++++++++ target/mips/tcg/sysemu/meson.build | 1 + 7 files changed, 161 insertions(+), 132 deletions(-) create mode 100644 target/mips/tcg/sysemu/special_helper.c