aboutsummaryrefslogtreecommitdiff
path: root/target/mips
diff options
context:
space:
mode:
authorPhilippe Mathieu-Daudé <f4bug@amsat.org>2021-04-13 21:40:33 +0200
committerPhilippe Mathieu-Daudé <f4bug@amsat.org>2021-05-02 16:49:35 +0200
commit8aa52bdc87aaf54c497902a91aaf4096cb780660 (patch)
tree26d914e38abb81cdc6d9713ea9908a984b7b2052 /target/mips
parent6575529b654ffeaebf1b00c53e33c834d68b7c33 (diff)
target/mips: Move exception management code to exception.c
Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Message-Id: <20210428170410.479308-27-f4bug@amsat.org>
Diffstat (limited to 'target/mips')
-rw-r--r--target/mips/cpu.c113
-rw-r--r--target/mips/exception.c167
-rw-r--r--target/mips/internal.h13
-rw-r--r--target/mips/meson.build1
-rw-r--r--target/mips/op_helper.c37
-rw-r--r--target/mips/tcg/tcg-internal.h14
6 files changed, 182 insertions, 163 deletions
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index a33e3b6c20..daa9a4791e 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -218,112 +218,12 @@ static void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
}
-static const char * const excp_names[EXCP_LAST + 1] = {
- [EXCP_RESET] = "reset",
- [EXCP_SRESET] = "soft reset",
- [EXCP_DSS] = "debug single step",
- [EXCP_DINT] = "debug interrupt",
- [EXCP_NMI] = "non-maskable interrupt",
- [EXCP_MCHECK] = "machine check",
- [EXCP_EXT_INTERRUPT] = "interrupt",
- [EXCP_DFWATCH] = "deferred watchpoint",
- [EXCP_DIB] = "debug instruction breakpoint",
- [EXCP_IWATCH] = "instruction fetch watchpoint",
- [EXCP_AdEL] = "address error load",
- [EXCP_AdES] = "address error store",
- [EXCP_TLBF] = "TLB refill",
- [EXCP_IBE] = "instruction bus error",
- [EXCP_DBp] = "debug breakpoint",
- [EXCP_SYSCALL] = "syscall",
- [EXCP_BREAK] = "break",
- [EXCP_CpU] = "coprocessor unusable",
- [EXCP_RI] = "reserved instruction",
- [EXCP_OVERFLOW] = "arithmetic overflow",
- [EXCP_TRAP] = "trap",
- [EXCP_FPE] = "floating point",
- [EXCP_DDBS] = "debug data break store",
- [EXCP_DWATCH] = "data watchpoint",
- [EXCP_LTLBL] = "TLB modify",
- [EXCP_TLBL] = "TLB load",
- [EXCP_TLBS] = "TLB store",
- [EXCP_DBE] = "data bus error",
- [EXCP_DDBL] = "debug data break load",
- [EXCP_THREAD] = "thread",
- [EXCP_MDMX] = "MDMX",
- [EXCP_C2E] = "precise coprocessor 2",
- [EXCP_CACHE] = "cache error",
- [EXCP_TLBXI] = "TLB execute-inhibit",
- [EXCP_TLBRI] = "TLB read-inhibit",
- [EXCP_MSADIS] = "MSA disabled",
- [EXCP_MSAFPE] = "MSA floating point",
-};
-
-const char *mips_exception_name(int32_t exception)
-{
- if (exception < 0 || exception > EXCP_LAST) {
- return "unknown";
- }
- return excp_names[exception];
-}
-
void cpu_set_exception_base(int vp_index, target_ulong address)
{
MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
vp->env.exception_base = address;
}
-target_ulong exception_resume_pc(CPUMIPSState *env)
-{
- target_ulong bad_pc;
- target_ulong isa_mode;
-
- isa_mode = !!(env->hflags & MIPS_HFLAG_M16);
- bad_pc = env->active_tc.PC | isa_mode;
- if (env->hflags & MIPS_HFLAG_BMASK) {
- /*
- * If the exception was raised from a delay slot, come back to
- * the jump.
- */
- bad_pc -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
- }
-
- return bad_pc;
-}
-
-bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
-{
- if (interrupt_request & CPU_INTERRUPT_HARD) {
- MIPSCPU *cpu = MIPS_CPU(cs);
- CPUMIPSState *env = &cpu->env;
-
- if (cpu_mips_hw_interrupts_enabled(env) &&
- cpu_mips_hw_interrupts_pending(env)) {
- /* Raise it */
- cs->exception_index = EXCP_EXT_INTERRUPT;
- env->error_code = 0;
- mips_cpu_do_interrupt(cs);
- return true;
- }
- }
- return false;
-}
-
-void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
- uint32_t exception,
- int error_code,
- uintptr_t pc)
-{
- CPUState *cs = env_cpu(env);
-
- qemu_log_mask(CPU_LOG_INT, "%s: %d (%s) %d\n",
- __func__, exception, mips_exception_name(exception),
- error_code);
- cs->exception_index = exception;
- env->error_code = error_code;
-
- cpu_loop_exit_restore(cs, pc);
-}
-
static void mips_cpu_set_pc(CPUState *cs, vaddr value)
{
MIPSCPU *cpu = MIPS_CPU(cs);
@@ -331,19 +231,6 @@ static void mips_cpu_set_pc(CPUState *cs, vaddr value)
mips_env_set_pc(&cpu->env, value);
}
-#ifdef CONFIG_TCG
-static void mips_cpu_synchronize_from_tb(CPUState *cs,
- const TranslationBlock *tb)
-{
- MIPSCPU *cpu = MIPS_CPU(cs);
- CPUMIPSState *env = &cpu->env;
-
- env->active_tc.PC = tb->pc;
- env->hflags &= ~MIPS_HFLAG_BMASK;
- env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
-}
-#endif /* CONFIG_TCG */
-
static bool mips_cpu_has_work(CPUState *cs)
{
MIPSCPU *cpu = MIPS_CPU(cs);
diff --git a/target/mips/exception.c b/target/mips/exception.c
new file mode 100644
index 0000000000..4fb8b00711
--- /dev/null
+++ b/target/mips/exception.c
@@ -0,0 +1,167 @@
+/*
+ * MIPS Exceptions processing helpers for QEMU.
+ *
+ * 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 "internal.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+
+target_ulong exception_resume_pc(CPUMIPSState *env)
+{
+ target_ulong bad_pc;
+ target_ulong isa_mode;
+
+ isa_mode = !!(env->hflags & MIPS_HFLAG_M16);
+ bad_pc = env->active_tc.PC | isa_mode;
+ if (env->hflags & MIPS_HFLAG_BMASK) {
+ /*
+ * If the exception was raised from a delay slot, come back to
+ * the jump.
+ */
+ bad_pc -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
+ }
+
+ return bad_pc;
+}
+
+void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
+ int error_code)
+{
+ do_raise_exception_err(env, exception, error_code, 0);
+}
+
+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);
+}
+
+void helper_wait(CPUMIPSState *env)
+{
+ CPUState *cs = env_cpu(env);
+
+ cs->halted = 1;
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
+ /*
+ * Last instruction in the block, PC was updated before
+ * - no need to recover PC and icount.
+ */
+ raise_exception(env, EXCP_HLT);
+}
+
+void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb)
+{
+ MIPSCPU *cpu = MIPS_CPU(cs);
+ CPUMIPSState *env = &cpu->env;
+
+ env->active_tc.PC = tb->pc;
+ env->hflags &= ~MIPS_HFLAG_BMASK;
+ env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
+}
+
+bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ MIPSCPU *cpu = MIPS_CPU(cs);
+ CPUMIPSState *env = &cpu->env;
+
+ if (cpu_mips_hw_interrupts_enabled(env) &&
+ cpu_mips_hw_interrupts_pending(env)) {
+ /* Raise it */
+ cs->exception_index = EXCP_EXT_INTERRUPT;
+ env->error_code = 0;
+ mips_cpu_do_interrupt(cs);
+ return true;
+ }
+ }
+ return false;
+}
+
+static const char * const excp_names[EXCP_LAST + 1] = {
+ [EXCP_RESET] = "reset",
+ [EXCP_SRESET] = "soft reset",
+ [EXCP_DSS] = "debug single step",
+ [EXCP_DINT] = "debug interrupt",
+ [EXCP_NMI] = "non-maskable interrupt",
+ [EXCP_MCHECK] = "machine check",
+ [EXCP_EXT_INTERRUPT] = "interrupt",
+ [EXCP_DFWATCH] = "deferred watchpoint",
+ [EXCP_DIB] = "debug instruction breakpoint",
+ [EXCP_IWATCH] = "instruction fetch watchpoint",
+ [EXCP_AdEL] = "address error load",
+ [EXCP_AdES] = "address error store",
+ [EXCP_TLBF] = "TLB refill",
+ [EXCP_IBE] = "instruction bus error",
+ [EXCP_DBp] = "debug breakpoint",
+ [EXCP_SYSCALL] = "syscall",
+ [EXCP_BREAK] = "break",
+ [EXCP_CpU] = "coprocessor unusable",
+ [EXCP_RI] = "reserved instruction",
+ [EXCP_OVERFLOW] = "arithmetic overflow",
+ [EXCP_TRAP] = "trap",
+ [EXCP_FPE] = "floating point",
+ [EXCP_DDBS] = "debug data break store",
+ [EXCP_DWATCH] = "data watchpoint",
+ [EXCP_LTLBL] = "TLB modify",
+ [EXCP_TLBL] = "TLB load",
+ [EXCP_TLBS] = "TLB store",
+ [EXCP_DBE] = "data bus error",
+ [EXCP_DDBL] = "debug data break load",
+ [EXCP_THREAD] = "thread",
+ [EXCP_MDMX] = "MDMX",
+ [EXCP_C2E] = "precise coprocessor 2",
+ [EXCP_CACHE] = "cache error",
+ [EXCP_TLBXI] = "TLB execute-inhibit",
+ [EXCP_TLBRI] = "TLB read-inhibit",
+ [EXCP_MSADIS] = "MSA disabled",
+ [EXCP_MSAFPE] = "MSA floating point",
+};
+
+const char *mips_exception_name(int32_t exception)
+{
+ if (exception < 0 || exception > EXCP_LAST) {
+ return "unknown";
+ }
+ return excp_names[exception];
+}
+
+void do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
+ int error_code, uintptr_t pc)
+{
+ CPUState *cs = env_cpu(env);
+
+ qemu_log_mask(CPU_LOG_INT, "%s: %d (%s) %d\n",
+ __func__, exception, mips_exception_name(exception),
+ error_code);
+ cs->exception_index = exception;
+ env->error_code = error_code;
+
+ cpu_loop_exit_restore(cs, pc);
+}
diff --git a/target/mips/internal.h b/target/mips/internal.h
index a1c7f658c2..07573c3e38 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -80,7 +80,6 @@ extern const char fregnames[32][4];
extern const struct mips_def_t mips_defs[];
extern const int mips_defs_number;
-bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
int mips_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
@@ -410,16 +409,4 @@ void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc);
void cpu_mips_store_status(CPUMIPSState *env, target_ulong val);
void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val);
-const char *mips_exception_name(int32_t exception);
-
-void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
- int error_code, uintptr_t 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
diff --git a/target/mips/meson.build b/target/mips/meson.build
index ff5eb210df..e08077bfc1 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -24,6 +24,7 @@ mips_tcg_ss = ss.source_set()
mips_tcg_ss.add(gen)
mips_tcg_ss.add(files(
'dsp_helper.c',
+ 'exception.c',
'fpu_helper.c',
'ldst_helper.c',
'lmmi_helper.c',
diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index cb2a7e96fc..ce1549c985 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -26,30 +26,6 @@
#include "exec/memop.h"
#include "fpu_helper.h"
-/*****************************************************************************/
-/* Exceptions processing helpers */
-
-void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception,
- int error_code)
-{
- do_raise_exception_err(env, exception, error_code, 0);
-}
-
-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);
-}
-
/* 64 bits arithmetic for 32 bits hosts */
static inline uint64_t get_HILO(CPUMIPSState *env)
{
@@ -399,19 +375,6 @@ void helper_pmon(CPUMIPSState *env, int function)
}
}
-void helper_wait(CPUMIPSState *env)
-{
- CPUState *cs = env_cpu(env);
-
- cs->halted = 1;
- cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
- /*
- * 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)
void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
diff --git a/target/mips/tcg/tcg-internal.h b/target/mips/tcg/tcg-internal.h
index 73667b3577..75aa3ef98e 100644
--- a/target/mips/tcg/tcg-internal.h
+++ b/target/mips/tcg/tcg-internal.h
@@ -14,11 +14,25 @@
#include "hw/core/cpu.h"
#include "cpu.h"
+void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb);
void mips_cpu_do_interrupt(CPUState *cpu);
+bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
+const char *mips_exception_name(int32_t exception);
+
+void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
+ int error_code, uintptr_t 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);
+}
+
#if !defined(CONFIG_USER_ONLY)
void mmu_init(CPUMIPSState *env, const mips_def_t *def);