summaryrefslogtreecommitdiff
path: root/target-m68k
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2007-05-26 15:09:38 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2007-05-26 15:09:38 +0000
commita87295e8df0923dab9857c1a340d23fe3278a336 (patch)
tree30c629030791710b509b88fceb184766f97743cd /target-m68k
parent20c9f095c4536e64e60432a5c72fce38e8306cbb (diff)
downloadqemu-a87295e8df0923dab9857c1a340d23fe3278a336.zip
M68k system mode semihosting.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2861 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-m68k')
-rw-r--r--target-m68k/cpu.h3
-rw-r--r--target-m68k/op.c7
-rw-r--r--target-m68k/op_helper.c16
-rw-r--r--target-m68k/translate.c4
4 files changed, 28 insertions, 2 deletions
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index c916ad7cd5..93080cfe12 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -51,6 +51,7 @@
#define EXCP_ICE 13
#define EXCP_RTE 0x100
+#define EXCP_HALT_INSN 0x101
typedef struct CPUM68KState {
uint32_t dregs[8];
@@ -148,6 +149,8 @@ void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector);
#define M68K_FPCR_PREC (1 << 6)
+void do_m68k_semihosting(CPUM68KState *env, int nr);
+
#ifdef CONFIG_USER_ONLY
/* Linux uses 8k pages. */
#define TARGET_PAGE_BITS 13
diff --git a/target-m68k/op.c b/target-m68k/op.c
index 6134bb018e..69d1fde9a7 100644
--- a/target-m68k/op.c
+++ b/target-m68k/op.c
@@ -383,8 +383,15 @@ OP(divs)
FORCE_RET();
}
+/* Halt is special because it may be a semihosting call. */
OP(halt)
{
+ RAISE_EXCEPTION(EXCP_HALT_INSN);
+ FORCE_RET();
+}
+
+OP(stop)
+{
env->halted = 1;
RAISE_EXCEPTION(EXCP_HLT);
FORCE_RET();
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 7455e31659..f5593eca0c 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -28,6 +28,8 @@ void do_interrupt(int is_hw)
#else
+extern int semihosting_enabled;
+
#define MMUSUFFIX _mmu
#define GETPC() (__builtin_return_address(0))
@@ -104,6 +106,20 @@ void do_interrupt(int is_hw)
/* Return from an exception. */
do_rte();
return;
+ case EXCP_HALT_INSN:
+ if (semihosting_enabled
+ && (env->sr & SR_S) != 0
+ && (env->pc & 3) == 0
+ && lduw_code(env->pc - 4) == 0x4e71
+ && ldl_code(env->pc) == 0x4e7bf000) {
+ env->pc += 4;
+ do_m68k_semihosting(env, env->dregs[0]);
+ return;
+ }
+ env->halted = 1;
+ env->exception_index = EXCP_HLT;
+ cpu_loop_exit();
+ return;
}
if (env->exception_index >= EXCP_TRAP0
&& env->exception_index <= EXCP_TRAP15) {
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index eff32867b8..d7162fea6f 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -1901,7 +1901,6 @@ DISAS_INSN(move_to_usp)
DISAS_INSN(halt)
{
- gen_flush_cc_op(s);
gen_jmp(s, gen_im32(s->pc));
gen_op_halt();
}
@@ -1919,7 +1918,8 @@ DISAS_INSN(stop)
s->pc += 2;
gen_set_sr_im(s, ext, 0);
- disas_halt(s, insn);
+ gen_jmp(s, gen_im32(s->pc));
+ gen_op_stop();
}
DISAS_INSN(rte)