aboutsummaryrefslogtreecommitdiff
path: root/target-m68k
diff options
context:
space:
mode:
Diffstat (limited to 'target-m68k')
-rw-r--r--target-m68k/cpu.c14
-rw-r--r--target-m68k/cpu.h9
-rw-r--r--target-m68k/helper.c23
-rw-r--r--target-m68k/m68k-semi.c5
-rw-r--r--target-m68k/op_helper.c34
-rw-r--r--target-m68k/qregs.def1
-rw-r--r--target-m68k/translate.c47
7 files changed, 71 insertions, 62 deletions
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 008d8db2da..c9cff19efc 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -30,6 +30,11 @@ static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
cpu->env.pc = value;
}
+static bool m68k_cpu_has_work(CPUState *cs)
+{
+ return cs->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
static void m68k_set_feature(CPUM68KState *env, int feature)
{
env->features |= (1u << feature);
@@ -44,7 +49,7 @@ static void m68k_cpu_reset(CPUState *s)
mcc->parent_reset(s);
- memset(env, 0, offsetof(CPUM68KState, breakpoints));
+ memset(env, 0, offsetof(CPUM68KState, features));
#if !defined(CONFIG_USER_ONLY)
env->sr = 0x2700;
#endif
@@ -53,7 +58,7 @@ static void m68k_cpu_reset(CPUState *s)
env->cc_op = CC_OP_FLAGS;
/* TODO: We should set PC from the interrupt vector. */
env->pc = 0;
- tlb_flush(env, 1);
+ tlb_flush(s, 1);
}
/* CPU models */
@@ -189,12 +194,15 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
cc->reset = m68k_cpu_reset;
cc->class_by_name = m68k_cpu_class_by_name;
+ cc->has_work = m68k_cpu_has_work;
cc->do_interrupt = m68k_cpu_do_interrupt;
cc->dump_state = m68k_cpu_dump_state;
cc->set_pc = m68k_cpu_set_pc;
cc->gdb_read_register = m68k_cpu_gdb_read_register;
cc->gdb_write_register = m68k_cpu_gdb_write_register;
-#ifndef CONFIG_USER_ONLY
+#ifdef CONFIG_USER_ONLY
+ cc->handle_mmu_fault = m68k_cpu_handle_mmu_fault;
+#else
cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
#endif
dc->vmsd = &vmstate_m68k_cpu;
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index cfd6846347..6e4001d523 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -110,6 +110,7 @@ typedef struct CPUM68KState {
CPU_COMMON
+ /* Fields from here on are preserved across CPU reset. */
uint32_t features;
} CPUM68KState;
@@ -237,9 +238,8 @@ static inline int cpu_mmu_index (CPUM68KState *env)
return (env->sr & SR_S) == 0 ? 1 : 0;
}
-int cpu_m68k_handle_mmu_fault(CPUM68KState *env, target_ulong address, int rw,
+int m68k_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
int mmu_idx);
-#define cpu_handle_mmu_fault cpu_m68k_handle_mmu_fault
#include "exec/cpu-all.h"
@@ -253,11 +253,6 @@ static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
| ((env->macsr >> 4) & 0xf); /* Bits 0-3 */
}
-static inline bool cpu_has_work(CPUState *cpu)
-{
- return cpu->interrupt_request & CPU_INTERRUPT_HARD;
-}
-
#include "exec/exec-all.h"
#endif
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index a364eb1e5c..077b653f24 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -132,6 +132,7 @@ void m68k_cpu_init_gdb(M68kCPU *cpu)
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
int flags;
uint32_t src;
uint32_t dest;
@@ -204,7 +205,7 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
flags |= CCF_C;
break;
default:
- cpu_abort(env, "Bad CC_OP %d", cc_op);
+ cpu_abort(CPU(cpu), "Bad CC_OP %d", cc_op);
}
env->cc_op = CC_OP_FLAGS;
env->cc_dest = flags;
@@ -212,6 +213,8 @@ void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
+
switch (reg) {
case 0x02: /* CACR */
env->cacr = val;
@@ -225,7 +228,7 @@ void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
break;
/* TODO: Implement control registers. */
default:
- cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
+ cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
reg, val);
}
}
@@ -277,11 +280,13 @@ void m68k_switch_sp(CPUM68KState *env)
#if defined(CONFIG_USER_ONLY)
-int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
- int mmu_idx)
+int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
+ int mmu_idx)
{
- env->exception_index = EXCP_ACCESS;
- env->mmu.ar = address;
+ M68kCPU *cpu = M68K_CPU(cs);
+
+ cs->exception_index = EXCP_ACCESS;
+ cpu->env.mmu.ar = address;
return 1;
}
@@ -295,14 +300,14 @@ hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
return addr;
}
-int cpu_m68k_handle_mmu_fault (CPUM68KState *env, target_ulong address, int rw,
- int mmu_idx)
+int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
+ int mmu_idx)
{
int prot;
address &= TARGET_PAGE_MASK;
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
+ tlb_set_page(cs, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
return 0;
}
diff --git a/target-m68k/m68k-semi.c b/target-m68k/m68k-semi.c
index 94c4983813..9dffe8de60 100644
--- a/target-m68k/m68k-semi.c
+++ b/target-m68k/m68k-semi.c
@@ -428,7 +428,8 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
case HOSTED_INIT_SIM:
#if defined(CONFIG_USER_ONLY)
{
- TaskState *ts = env->opaque;
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
+ TaskState *ts = cs->opaque;
/* Allocate the heap using sbrk. */
if (!ts->heap_limit) {
abi_ulong ret;
@@ -460,7 +461,7 @@ void do_m68k_semihosting(CPUM68KState *env, int nr)
#endif
return;
default:
- cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
+ cpu_abort(CPU(m68k_env_get_cpu(env)), "Unsupported semihosting syscall %d\n", nr);
result = 0;
}
failed:
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index bbbfd7f130..06302b1071 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -23,10 +23,7 @@
void m68k_cpu_do_interrupt(CPUState *cs)
{
- M68kCPU *cpu = M68K_CPU(cs);
- CPUM68KState *env = &cpu->env;
-
- env->exception_index = -1;
+ cs->exception_index = -1;
}
void do_interrupt_m68k_hardirq(CPUM68KState *env)
@@ -56,18 +53,18 @@ extern int semihosting_enabled;
/* Try to fill the TLB and return an exception if error. If retaddr is
NULL, it means that the function was called in C code (i.e. not
from generated code or from helper.c) */
-void tlb_fill(CPUM68KState *env, target_ulong addr, int is_write, int mmu_idx,
+void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
int ret;
- ret = cpu_m68k_handle_mmu_fault(env, addr, is_write, mmu_idx);
+ ret = m68k_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx);
if (unlikely(ret)) {
if (retaddr) {
/* now we have a real cpu fault */
- cpu_restore_state(env, retaddr);
+ cpu_restore_state(cs, retaddr);
}
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
}
}
@@ -87,7 +84,7 @@ static void do_rte(CPUM68KState *env)
static void do_interrupt_all(CPUM68KState *env, int is_hw)
{
- CPUState *cs;
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
uint32_t sp;
uint32_t fmt;
uint32_t retaddr;
@@ -97,7 +94,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
retaddr = env->pc;
if (!is_hw) {
- switch (env->exception_index) {
+ switch (cs->exception_index) {
case EXCP_RTE:
/* Return from an exception. */
do_rte(env);
@@ -112,20 +109,19 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
do_m68k_semihosting(env, env->dregs[0]);
return;
}
- cs = CPU(m68k_env_get_cpu(env));
cs->halted = 1;
- env->exception_index = EXCP_HLT;
- cpu_loop_exit(env);
+ cs->exception_index = EXCP_HLT;
+ cpu_loop_exit(cs);
return;
}
- if (env->exception_index >= EXCP_TRAP0
- && env->exception_index <= EXCP_TRAP15) {
+ if (cs->exception_index >= EXCP_TRAP0
+ && cs->exception_index <= EXCP_TRAP15) {
/* Move the PC after the trap instruction. */
retaddr += 2;
}
}
- vector = env->exception_index << 2;
+ vector = cs->exception_index << 2;
sp = env->aregs[7];
@@ -168,8 +164,10 @@ void do_interrupt_m68k_hardirq(CPUM68KState *env)
static void raise_exception(CPUM68KState *env, int tt)
{
- env->exception_index = tt;
- cpu_loop_exit(env);
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
+
+ cs->exception_index = tt;
+ cpu_loop_exit(cs);
}
void HELPER(raise_exception)(CPUM68KState *env, uint32_t tt)
diff --git a/target-m68k/qregs.def b/target-m68k/qregs.def
index 4235b02764..204663e1aa 100644
--- a/target-m68k/qregs.def
+++ b/target-m68k/qregs.def
@@ -7,6 +7,5 @@ DEFO32(CC_SRC, cc_src)
DEFO32(CC_X, cc_x)
DEFO32(DIV1, div1)
DEFO32(DIV2, div2)
-DEFO32(EXCEPTION, exception_index)
DEFO32(MACSR, macsr)
DEFO32(MAC_MASK, mac_mask)
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index f54b94a53f..cd662891c8 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -43,6 +43,7 @@
#undef DEFF64
static TCGv_i32 cpu_halted;
+static TCGv_i32 cpu_exception_index;
static TCGv_ptr cpu_env;
@@ -81,6 +82,10 @@ void m68k_tcg_init(void)
cpu_halted = tcg_global_mem_new_i32(TCG_AREG0,
-offsetof(M68kCPU, env) +
offsetof(CPUState, halted), "HALTED");
+ cpu_exception_index = tcg_global_mem_new_i32(TCG_AREG0,
+ -offsetof(M68kCPU, env) +
+ offsetof(CPUState, exception_index),
+ "EXCEPTION");
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
@@ -110,14 +115,6 @@ void m68k_tcg_init(void)
store_dummy = tcg_global_mem_new(TCG_AREG0, -8, "NULL");
}
-static inline void qemu_assert(int cond, const char *msg)
-{
- if (!cond) {
- fprintf (stderr, "badness: %s\n", msg);
- abort();
- }
-}
-
/* internal defines */
typedef struct DisasContext {
CPUM68KState *env;
@@ -199,7 +196,7 @@ static inline TCGv gen_load(DisasContext * s, int opsize, TCGv addr, int sign)
tcg_gen_qemu_ld32u(tmp, addr, index);
break;
default:
- qemu_assert(0, "bad load size");
+ g_assert_not_reached();
}
gen_throws_exception = gen_last_qop;
return tmp;
@@ -233,7 +230,7 @@ static inline void gen_store(DisasContext *s, int opsize, TCGv addr, TCGv val)
tcg_gen_qemu_st32(val, addr, index);
break;
default:
- qemu_assert(0, "bad store size");
+ g_assert_not_reached();
}
gen_throws_exception = gen_last_qop;
}
@@ -437,8 +434,7 @@ static inline int opsize_bytes(int opsize)
case OS_SINGLE: return 4;
case OS_DOUBLE: return 8;
default:
- qemu_assert(0, "bad operand size");
- return 0;
+ g_assert_not_reached();
}
}
@@ -465,8 +461,7 @@ static void gen_partset_reg(int opsize, TCGv reg, TCGv val)
tcg_gen_mov_i32(reg, val);
break;
default:
- qemu_assert(0, "Bad operand size");
- break;
+ g_assert_not_reached();
}
}
@@ -495,7 +490,7 @@ static inline TCGv gen_extend(TCGv val, int opsize, int sign)
tmp = val;
break;
default:
- qemu_assert(0, "Bad operand size");
+ g_assert_not_reached();
}
return tmp;
}
@@ -669,7 +664,7 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
offset = read_im32(env, s);
break;
default:
- qemu_assert(0, "Bad immediate operand");
+ g_assert_not_reached();
}
return tcg_const_i32(offset);
default:
@@ -886,8 +881,10 @@ DISAS_INSN(undef_fpu)
DISAS_INSN(undef)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
+
gen_exception(s, s->pc - 2, EXCP_UNSUPPORTED);
- cpu_abort(env, "Illegal instruction: %04x @ %08x", insn, s->pc - 2);
+ cpu_abort(CPU(cpu), "Illegal instruction: %04x @ %08x", insn, s->pc - 2);
}
DISAS_INSN(mulw)
@@ -2087,12 +2084,14 @@ DISAS_INSN(wddata)
DISAS_INSN(wdebug)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
+
if (IS_USER(s)) {
gen_exception(s, s->pc - 2, EXCP_PRIVILEGE);
return;
}
/* TODO: Implement wdebug. */
- qemu_assert(0, "WDEBUG not implemented");
+ cpu_abort(CPU(cpu), "WDEBUG not implemented");
}
DISAS_INSN(trap)
@@ -2466,14 +2465,18 @@ DISAS_INSN(fbcc)
DISAS_INSN(frestore)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
+
/* TODO: Implement frestore. */
- qemu_assert(0, "FRESTORE not implemented");
+ cpu_abort(CPU(cpu), "FRESTORE not implemented");
}
DISAS_INSN(fsave)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
+
/* TODO: Implement fsave. */
- qemu_assert(0, "FSAVE not implemented");
+ cpu_abort(CPU(cpu), "FSAVE not implemented");
}
static inline TCGv gen_mac_extract_word(DisasContext *s, TCGv val, int upper)
@@ -3008,8 +3011,8 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
do {
pc_offset = dc->pc - pc_start;
gen_throws_exception = NULL;
- if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_exception(dc, dc->pc, EXCP_DEBUG);
dc->is_jmp = DISAS_JUMP;