diff options
author | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-05-26 15:09:38 +0000 |
---|---|---|
committer | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-05-26 15:09:38 +0000 |
commit | a87295e8df0923dab9857c1a340d23fe3278a336 (patch) | |
tree | 30c629030791710b509b88fceb184766f97743cd /target-m68k | |
parent | 20c9f095c4536e64e60432a5c72fce38e8306cbb (diff) |
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.h | 3 | ||||
-rw-r--r-- | target-m68k/op.c | 7 | ||||
-rw-r--r-- | target-m68k/op_helper.c | 16 | ||||
-rw-r--r-- | target-m68k/translate.c | 4 |
4 files changed, 28 insertions, 2 deletions
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index c916ad7cd..93080cfe1 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 6134bb018..69d1fde9a 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 7455e3165..f5593eca0 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 eff32867b..d7162fea6 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) |