diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-10-25 21:35:50 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-10-25 21:35:50 +0000 |
commit | 0411a9725829d626bb0b2f11a461463c96061682 (patch) | |
tree | 105135188a4e2af4e3cf44518f5e2b14a7e83e01 /target-ppc/op_helper.c | |
parent | 7ac256b8725304aabae78bf012c25b6416509c46 (diff) |
Gprof prooved the PowerPC emulation spent too much time in MSR load and store
routines. Coming back to a raw MSR storage model then speed-up the emulation.
Improve fast MSR updates (wrtee wrteei and mtriee cases).
Share rfi family instructions helpers code to avoid bug in duplicated code.
Allow entering halt mode as the result of a rfi instruction.
Add a new helper_regs.h file to avoid duplication of special registers
manipulation routines (currently XER and MSR).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3436 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/op_helper.c')
-rw-r--r-- | target-ppc/op_helper.c | 149 |
1 files changed, 48 insertions, 101 deletions
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index f5331bace4..c654b139cc 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -19,6 +19,7 @@ */ #include "exec.h" +#include "helper_regs.h" #include "op_helper.h" #define MEMSUFFIX _raw @@ -98,24 +99,6 @@ void do_store_cr (uint32_t mask) } } -void do_load_xer (void) -{ - T0 = (xer_so << XER_SO) | - (xer_ov << XER_OV) | - (xer_ca << XER_CA) | - (xer_bc << XER_BC) | - (xer_cmp << XER_CMP); -} - -void do_store_xer (void) -{ - xer_so = (T0 >> XER_SO) & 0x01; - xer_ov = (T0 >> XER_OV) & 0x01; - xer_ca = (T0 >> XER_CA) & 0x01; - xer_cmp = (T0 >> XER_CMP) & 0xFF; - xer_bc = (T0 >> XER_BC) & 0x7F; -} - #if defined(TARGET_PPC64) void do_store_pri (int prio) { @@ -970,56 +953,63 @@ void do_fcmpo (void) #if !defined (CONFIG_USER_ONLY) void cpu_dump_rfi (target_ulong RA, target_ulong msr); -void do_rfi (void) + +void do_store_msr (void) +{ + T0 = hreg_store_msr(env, T0); + if (T0 != 0) { + env->interrupt_request |= CPU_INTERRUPT_EXITTB; + do_raise_exception(T0); + } +} + +static always_inline void __do_rfi (target_ulong nip, target_ulong msr, + target_ulong msrm, int keep_msrh) { #if defined(TARGET_PPC64) - if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) { - env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003); - do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL)); + if (msr & (1ULL << MSR_SF)) { + nip = (uint64_t)nip; + msr &= (uint64_t)msrm; } else { - env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003); - ppc_store_msr_32(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL)); + nip = (uint32_t)nip; + msr = (uint32_t)(msr & msrm); + if (keep_msrh) + msr |= env->msr & ~((uint64_t)0xFFFFFFFF); } #else - env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003); - do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL)); + nip = (uint32_t)nip; + msr &= (uint32_t)msrm; #endif + /* XXX: beware: this is false if VLE is supported */ + env->nip = nip & ~((target_ulong)0x00000003); + hreg_store_msr(env, msr); #if defined (DEBUG_OP) - cpu_dump_rfi(env->nip, do_load_msr(env)); + cpu_dump_rfi(env->nip, env->msr); #endif + /* No need to raise an exception here, + * as rfi is always the last insn of a TB + */ env->interrupt_request |= CPU_INTERRUPT_EXITTB; } +void do_rfi (void) +{ + __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1], + ~((target_ulong)0xFFFF0000), 1); +} + #if defined(TARGET_PPC64) void do_rfid (void) { - if (env->spr[SPR_SRR1] & (1ULL << MSR_SF)) { - env->nip = (uint64_t)(env->spr[SPR_SRR0] & ~0x00000003); - do_store_msr(env, (uint64_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL)); - } else { - env->nip = (uint32_t)(env->spr[SPR_SRR0] & ~0x00000003); - do_store_msr(env, (uint32_t)(env->spr[SPR_SRR1] & ~0xFFFF0000UL)); - } -#if defined (DEBUG_OP) - cpu_dump_rfi(env->nip, do_load_msr(env)); -#endif - env->interrupt_request |= CPU_INTERRUPT_EXITTB; + __do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1], + ~((target_ulong)0xFFFF0000), 0); } #endif #if defined(TARGET_PPC64H) void do_hrfid (void) { - if (env->spr[SPR_HSRR1] & (1ULL << MSR_SF)) { - env->nip = (uint64_t)(env->spr[SPR_HSRR0] & ~0x00000003); - do_store_msr(env, (uint64_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL)); - } else { - env->nip = (uint32_t)(env->spr[SPR_HSRR0] & ~0x00000003); - do_store_msr(env, (uint32_t)(env->spr[SPR_HSRR1] & ~0xFFFF0000UL)); - } -#if defined (DEBUG_OP) - cpu_dump_rfi(env->nip, do_load_msr(env)); -#endif - env->interrupt_request |= CPU_INTERRUPT_EXITTB; + __do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1], + ~((target_ulong)0xFFFF0000), 0); } #endif #endif @@ -1214,13 +1204,7 @@ void do_POWER_rac (void) void do_POWER_rfsvc (void) { - env->nip = env->lr & ~0x00000003UL; - T0 = env->ctr & 0x0000FFFFUL; - do_store_msr(env, T0); -#if defined (DEBUG_OP) - cpu_dump_rfi(env->nip, do_load_msr(env)); -#endif - env->interrupt_request |= CPU_INTERRUPT_EXITTB; + __do_rfi(env->lr, env->ctr, 0x0000FFFF, 0); } /* PowerPC 601 BAT management helper */ @@ -1332,63 +1316,26 @@ void do_store_dcr (void) #if !defined(CONFIG_USER_ONLY) void do_40x_rfci (void) { - env->nip = env->spr[SPR_40x_SRR2]; - do_store_msr(env, env->spr[SPR_40x_SRR3] & ~0xFFFF0000); -#if defined (DEBUG_OP) - cpu_dump_rfi(env->nip, do_load_msr(env)); -#endif - env->interrupt_request = CPU_INTERRUPT_EXITTB; + __do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3], + ~((target_ulong)0xFFFF0000), 0); } void do_rfci (void) { -#if defined(TARGET_PPC64) - if (env->spr[SPR_BOOKE_CSRR1] & (1 << MSR_CM)) { - env->nip = (uint64_t)env->spr[SPR_BOOKE_CSRR0]; - } else -#endif - { - env->nip = (uint32_t)env->spr[SPR_BOOKE_CSRR0]; - } - do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_CSRR1] & ~0x3FFF0000); -#if defined (DEBUG_OP) - cpu_dump_rfi(env->nip, do_load_msr(env)); -#endif - env->interrupt_request = CPU_INTERRUPT_EXITTB; + __do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1, + ~((target_ulong)0x3FFF0000), 0); } void do_rfdi (void) { -#if defined(TARGET_PPC64) - if (env->spr[SPR_BOOKE_DSRR1] & (1 << MSR_CM)) { - env->nip = (uint64_t)env->spr[SPR_BOOKE_DSRR0]; - } else -#endif - { - env->nip = (uint32_t)env->spr[SPR_BOOKE_DSRR0]; - } - do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_DSRR1] & ~0x3FFF0000); -#if defined (DEBUG_OP) - cpu_dump_rfi(env->nip, do_load_msr(env)); -#endif - env->interrupt_request = CPU_INTERRUPT_EXITTB; + __do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1, + ~((target_ulong)0x3FFF0000), 0); } void do_rfmci (void) { -#if defined(TARGET_PPC64) - if (env->spr[SPR_BOOKE_MCSRR1] & (1 << MSR_CM)) { - env->nip = (uint64_t)env->spr[SPR_BOOKE_MCSRR0]; - } else -#endif - { - env->nip = (uint32_t)env->spr[SPR_BOOKE_MCSRR0]; - } - do_store_msr(env, (uint32_t)env->spr[SPR_BOOKE_MCSRR1] & ~0x3FFF0000); -#if defined (DEBUG_OP) - cpu_dump_rfi(env->nip, do_load_msr(env)); -#endif - env->interrupt_request = CPU_INTERRUPT_EXITTB; + __do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1, + ~((target_ulong)0x3FFF0000), 0); } void do_load_403_pb (int num) |