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:
Philippe Mathieu-Daudé 2021-04-13 20:19:52 +02:00
parent f3185ec2f3
commit d60146a938
7 changed files with 151 additions and 122 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -1,5 +1,6 @@
mips_softmmu_ss.add(files(
'cp0_helper.c',
'mips-semi.c',
'special_helper.c',
'tlb_helper.c',
))

View 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);
}

View File

@ -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)

View File

@ -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);