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,6 +274,17 @@ int cpu_exec(CPUState *env1) | ||
| 274 | return EXCP_HALTED; | 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 | #endif | 288 | #endif |
| 278 | 289 | ||
| 279 | cpu_single_env = env1; | 290 | cpu_single_env = env1; |
target-arm/cpu.h
| @@ -90,7 +90,7 @@ typedef struct CPUARMState { | @@ -90,7 +90,7 @@ typedef struct CPUARMState { | ||
| 90 | int exception_index; | 90 | int exception_index; |
| 91 | int interrupt_request; | 91 | int interrupt_request; |
| 92 | int user_mode_only; | 92 | int user_mode_only; |
| 93 | - uint32_t address; | 93 | + int halted; |
| 94 | 94 | ||
| 95 | /* VFP coprocessor state. */ | 95 | /* VFP coprocessor state. */ |
| 96 | struct { | 96 | struct { |
target-arm/op.c
| @@ -878,6 +878,13 @@ void OPPROTO op_debug(void) | @@ -878,6 +878,13 @@ void OPPROTO op_debug(void) | ||
| 878 | cpu_loop_exit(); | 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 | /* VFP support. We follow the convention used for VFP instrunctions: | 888 | /* VFP support. We follow the convention used for VFP instrunctions: |
| 882 | Single precition routines have a "s" suffix, double precision a | 889 | Single precition routines have a "s" suffix, double precision a |
| 883 | "d" suffix. */ | 890 | "d" suffix. */ |
target-arm/translate.c
| @@ -496,6 +496,15 @@ static int disas_cp15_insn(DisasContext *s, uint32_t insn) | @@ -496,6 +496,15 @@ static int disas_cp15_insn(DisasContext *s, uint32_t insn) | ||
| 496 | if (IS_USER(s)) { | 496 | if (IS_USER(s)) { |
| 497 | return 1; | 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 | rd = (insn >> 12) & 0xf; | 508 | rd = (insn >> 12) & 0xf; |
| 500 | if (insn & (1 << 20)) { | 509 | if (insn & (1 << 20)) { |
| 501 | gen_op_movl_T0_cp15(insn); | 510 | gen_op_movl_T0_cp15(insn); |