Commit 9332f9dafa33b085488a5369333213d549dbdc7f
1 parent
e8ebb8a8
ARM CPU suspend/halt (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1663 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
28 additions
and
1 deletions
cpu-exec.c
| ... | ... | @@ -274,6 +274,17 @@ int cpu_exec(CPUState *env1) |
| 274 | 274 | return EXCP_HALTED; |
| 275 | 275 | } |
| 276 | 276 | } |
| 277 | +#elif defined(TARGET_ARM) | |
| 278 | + if (env1->halted) { | |
| 279 | + /* An interrupt wakes the CPU even if the I and F CPSR bits are | |
| 280 | + set. */ | |
| 281 | + if (env1->interrupt_request | |
| 282 | + & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) { | |
| 283 | + env1->halted = 0; | |
| 284 | + } else { | |
| 285 | + return EXCP_HALTED; | |
| 286 | + } | |
| 287 | + } | |
| 277 | 288 | #endif |
| 278 | 289 | |
| 279 | 290 | cpu_single_env = env1; | ... | ... |
target-arm/cpu.h
target-arm/op.c
| ... | ... | @@ -878,6 +878,13 @@ void OPPROTO op_debug(void) |
| 878 | 878 | cpu_loop_exit(); |
| 879 | 879 | } |
| 880 | 880 | |
| 881 | +void OPPROTO op_wfi(void) | |
| 882 | +{ | |
| 883 | + env->exception_index = EXCP_HLT; | |
| 884 | + env->halted = 1; | |
| 885 | + cpu_loop_exit(); | |
| 886 | +} | |
| 887 | + | |
| 881 | 888 | /* VFP support. We follow the convention used for VFP instrunctions: |
| 882 | 889 | Single precition routines have a "s" suffix, double precision a |
| 883 | 890 | "d" suffix. */ | ... | ... |
target-arm/translate.c
| ... | ... | @@ -496,6 +496,15 @@ static int disas_cp15_insn(DisasContext *s, uint32_t insn) |
| 496 | 496 | if (IS_USER(s)) { |
| 497 | 497 | return 1; |
| 498 | 498 | } |
| 499 | + if ((insn & 0x0fff0fff) == 0x0e070f90 | |
| 500 | + || (insn & 0x0fff0fff) == 0x0e070f58) { | |
| 501 | + /* Wait for interrupt. */ | |
| 502 | + gen_op_movl_T0_im((long)s->pc); | |
| 503 | + gen_op_movl_reg_TN[0][15](); | |
| 504 | + gen_op_wfi(); | |
| 505 | + s->is_jmp = DISAS_JUMP; | |
| 506 | + return 0; | |
| 507 | + } | |
| 499 | 508 | rd = (insn >> 12) & 0xf; |
| 500 | 509 | if (insn & (1 << 20)) { |
| 501 | 510 | gen_op_movl_T0_cp15(insn); | ... | ... |