aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-11-26 20:15:14 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-11-26 20:15:14 +0000
commit50443c98e4149e8cde3b371f9ed60d943d95d286 (patch)
tree1d091d1e6bd2311470eab59ec5f08cae89c0f4f9
parent6f5a9f7e56ab8dfeacca9ac779c0661261642873 (diff)
specialize the power save code for 7x0 CPUs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1671 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--cpu-exec.c4
-rw-r--r--monitor.c2
-rw-r--r--target-ppc/cpu.h2
-rw-r--r--target-ppc/helper.c15
4 files changed, 19 insertions, 4 deletions
diff --git a/cpu-exec.c b/cpu-exec.c
index 5c85c1e9d8..89bf8b85e1 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -265,11 +265,11 @@ int cpu_exec(CPUState *env1)
}
}
#elif defined(TARGET_PPC)
- if (env1->msr[MSR_POW]) {
+ if (env1->halted) {
if (env1->msr[MSR_EE] &&
(env1->interrupt_request &
(CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
- env1->msr[MSR_POW] = 0;
+ env1->halted = 0;
} else {
return EXCP_HALTED;
}
diff --git a/monitor.c b/monitor.c
index 70b473ddbf..2f0e84d86e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -257,7 +257,7 @@ static void do_info_cpus(void)
term_printf(" (halted)");
#elif defined(TARGET_PPC)
term_printf(" nip=0x" TARGET_FMT_lx, env->nip);
- if (msr_pow)
+ if (env->halted)
term_printf(" (halted)");
#endif
term_printf("\n");
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index fa7f524e9d..88d91358e2 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -495,6 +495,8 @@ struct CPUPPCState {
CPU_COMMON
+ int halted; /* TRUE if the CPU is in suspend state */
+
int access_type; /* when a memory exception occurs, the access
type is stored here */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index ff1355c541..3f7a708712 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -807,6 +807,8 @@ void do_compute_hflags (CPUPPCState *env)
void do_store_msr (CPUPPCState *env, target_ulong value)
{
+ int enter_pm;
+
value &= env->msr_mask;
if (((value >> MSR_IR) & 1) != msr_ir ||
((value >> MSR_DR) & 1) != msr_dr) {
@@ -846,8 +848,19 @@ void do_store_msr (CPUPPCState *env, target_ulong value)
msr_ri = (value >> MSR_RI) & 1;
msr_le = (value >> MSR_LE) & 1;
do_compute_hflags(env);
- if (msr_pow) {
+
+ enter_pm = 0;
+ switch (PPC_EXCP(env)) {
+ case PPC_FLAGS_EXCP_7x0:
+ if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0)
+ enter_pm = 1;
+ break;
+ default:
+ break;
+ }
+ if (enter_pm) {
/* power save: exit cpu loop */
+ env->halted = 1;
env->exception_index = EXCP_HLT;
cpu_loop_exit();
}