target/mips: Move Special opcodes to tcg/sysemu/special_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". Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Message-Id: <20210428170410.479308-24-f4bug@amsat.org>
This commit is contained in:
parent
f3185ec2f3
commit
d60146a938
@ -342,23 +342,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)
|
||||
|
@ -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)
|
||||
|
@ -655,106 +655,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 inline void exception_return(CPUMIPSState *env)
|
||||
{
|
||||
debug_pre_eret(env);
|
||||
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||
mips_env_set_pc(env, env->CP0_ErrorEPC);
|
||||
env->CP0_Status &= ~(1 << CP0St_ERL);
|
||||
} else {
|
||||
mips_env_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);
|
||||
|
||||
mips_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)
|
||||
|
@ -1,5 +1,6 @@
|
||||
mips_softmmu_ss.add(files(
|
||||
'cp0_helper.c',
|
||||
'mips-semi.c',
|
||||
'special_helper.c',
|
||||
'tlb_helper.c',
|
||||
))
|
||||
|
140
target/mips/tcg/sysemu/special_helper.c
Normal file
140
target/mips/tcg/sysemu/special_helper.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
mips_env_set_pc(env, env->CP0_ErrorEPC);
|
||||
env->CP0_Status &= ~(1 << CP0St_ERL);
|
||||
} else {
|
||||
mips_env_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);
|
||||
|
||||
mips_env_set_pc(env, env->CP0_DEPC);
|
||||
|
||||
debug_post_eret(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)
|
||||
|
@ -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, uintptr_t retaddr);
|
||||
void cpu_mips_tlb_flush(CPUMIPSState *env);
|
||||
|
Loading…
Reference in New Issue
Block a user