diff options
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/cpu.h | 16 | ||||
-rw-r--r-- | target-ppc/excp_helper.c | 40 | ||||
-rw-r--r-- | target-ppc/kvm.c | 12 | ||||
-rw-r--r-- | target-ppc/machine.c | 8 | ||||
-rw-r--r-- | target-ppc/translate.c | 29 |
5 files changed, 64 insertions, 41 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index bb5b0a4a99..5f1dc8b7d5 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -963,7 +963,7 @@ struct CPUPPCState { /* floating point registers */ float64 fpr[32]; /* floating point status and control register */ - uint32_t fpscr; + target_ulong fpscr; /* Next instruction pointer */ target_ulong nip; @@ -1014,6 +1014,8 @@ struct CPUPPCState { /* Altivec registers */ ppc_avr_t avr[32]; uint32_t vscr; + /* VSX registers */ + uint64_t vsr[32]; /* SPE registers */ uint64_t spe_acc; uint32_t spe_fscr; @@ -1045,9 +1047,9 @@ struct CPUPPCState { #endif #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) - hwaddr vpa_addr; - hwaddr slb_shadow_addr, slb_shadow_size; - hwaddr dtl_addr, dtl_size; + uint64_t vpa_addr; + uint64_t slb_shadow_addr, slb_shadow_size; + uint64_t dtl_addr, dtl_size; #endif /* TARGET_PPC64 */ int error_code; @@ -2213,10 +2215,12 @@ static inline bool msr_is_64bit(CPUPPCState *env, target_ulong msr) return msr & (1ULL << MSR_SF); } -extern void (*cpu_ppc_hypercall)(CPUPPCState *); +extern void (*cpu_ppc_hypercall)(PowerPCCPU *); -static inline bool cpu_has_work(CPUPPCState *env) +static inline bool cpu_has_work(CPUState *cpu) { + CPUPPCState *env = &POWERPC_CPU(cpu)->env; + return msr_ee && (env->interrupt_request & CPU_INTERRUPT_HARD); } diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index 1a593f6f3f..5e34ad08a8 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -33,7 +33,7 @@ /*****************************************************************************/ /* PowerPC Hypercall emulation */ -void (*cpu_ppc_hypercall)(CPUPPCState *); +void (*cpu_ppc_hypercall)(PowerPCCPU *); /*****************************************************************************/ /* Exception processing */ @@ -63,8 +63,9 @@ static inline void dump_syscall(CPUPPCState *env) /* Note that this function should be greatly optimized * when called with a constant excp, from ppc_hw_interrupt */ -static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) +static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) { + CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; int srr0, srr1, asrr0, asrr1; int lpes0, lpes1, lev; @@ -238,7 +239,7 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) dump_syscall(env); lev = env->error_code; if ((lev == 1) && cpu_ppc_hypercall) { - cpu_ppc_hypercall(env); + cpu_ppc_hypercall(cpu); return; } if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) { @@ -643,11 +644,14 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp) void do_interrupt(CPUPPCState *env) { - powerpc_excp(env, env->excp_model, env->exception_index); + PowerPCCPU *cpu = ppc_env_get_cpu(env); + + powerpc_excp(cpu, env->excp_model, env->exception_index); } void ppc_hw_interrupt(CPUPPCState *env) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); int hdice; #if 0 @@ -658,20 +662,20 @@ void ppc_hw_interrupt(CPUPPCState *env) /* External reset */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); return; } /* Machine check exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK); return; } #if 0 /* TODO */ /* External debug exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG); return; } #endif @@ -685,7 +689,7 @@ void ppc_hw_interrupt(CPUPPCState *env) /* Hypervisor decrementer exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); return; } } @@ -698,7 +702,7 @@ void ppc_hw_interrupt(CPUPPCState *env) #if 0 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT); #endif - powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL); return; } } @@ -706,30 +710,30 @@ void ppc_hw_interrupt(CPUPPCState *env) /* Watchdog timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI); return; } /* Fixed interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT); return; } /* Programmable interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT); return; } /* Decrementer exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); return; } /* External interrupt */ @@ -740,23 +744,23 @@ void ppc_hw_interrupt(CPUPPCState *env) #if 0 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT); #endif - powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM); return; } /* Thermal interrupt */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); - powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM); + powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM); return; } } diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 5cbe98a164..3f5df5772f 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -73,9 +73,11 @@ static int cap_hior; */ static QEMUTimer *idle_timer; -static void kvm_kick_env(void *env) +static void kvm_kick_cpu(void *opaque) { - qemu_cpu_kick(env); + PowerPCCPU *cpu = opaque; + + qemu_cpu_kick(CPU(cpu)); } int kvm_arch_init(KVMState *s) @@ -375,6 +377,7 @@ static inline void kvm_fixup_page_sizes(CPUPPCState *env) int kvm_arch_init_vcpu(CPUPPCState *cenv) { + PowerPCCPU *cpu = ppc_env_get_cpu(cenv); int ret; /* Gather server mmu info from KVM and update the CPU state */ @@ -386,7 +389,7 @@ int kvm_arch_init_vcpu(CPUPPCState *cenv) return ret; } - idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_env, cenv); + idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_cpu, cpu); /* Some targets support access to KVM's guest TLB. */ switch (cenv->mmu_model) { @@ -814,7 +817,8 @@ int kvm_arch_handle_exit(CPUPPCState *env, struct kvm_run *run) #ifdef CONFIG_PSERIES case KVM_EXIT_PAPR_HCALL: dprintf("handle PAPR hypercall\n"); - run->papr_hcall.ret = spapr_hypercall(env, run->papr_hcall.nr, + run->papr_hcall.ret = spapr_hypercall(ppc_env_get_cpu(env), + run->papr_hcall.nr, run->papr_hcall.args); ret = 0; break; diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 21ce7575e3..5e7bc00e26 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -6,6 +6,7 @@ void cpu_save(QEMUFile *f, void *opaque) { CPUPPCState *env = (CPUPPCState *)opaque; unsigned int i, j; + uint32_t fpscr; for (i = 0; i < 32; i++) qemu_put_betls(f, &env->gpr[i]); @@ -30,7 +31,8 @@ void cpu_save(QEMUFile *f, void *opaque) u.d = env->fpr[i]; qemu_put_be64(f, u.l); } - qemu_put_be32s(f, &env->fpscr); + fpscr = env->fpscr; + qemu_put_be32s(f, &fpscr); qemu_put_sbe32s(f, &env->access_type); #if defined(TARGET_PPC64) qemu_put_betls(f, &env->asr); @@ -90,6 +92,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) CPUPPCState *env = (CPUPPCState *)opaque; unsigned int i, j; target_ulong sdr1; + uint32_t fpscr; for (i = 0; i < 32; i++) qemu_get_betls(f, &env->gpr[i]); @@ -114,7 +117,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) u.l = qemu_get_be64(f); env->fpr[i] = u.d; } - qemu_get_be32s(f, &env->fpscr); + qemu_get_be32s(f, &fpscr); + env->fpscr = fpscr; qemu_get_sbe32s(f, &env->access_type); #if defined(TARGET_PPC64) qemu_get_betls(f, &env->asr); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 1042268ecf..56725e6a61 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -68,7 +68,7 @@ static TCGv cpu_cfar; #endif static TCGv cpu_xer; static TCGv cpu_reserve; -static TCGv_i32 cpu_fpscr; +static TCGv cpu_fpscr; static TCGv_i32 cpu_access_type; #include "gen-icount.h" @@ -163,8 +163,8 @@ void ppc_translate_init(void) offsetof(CPUPPCState, reserve_addr), "reserve_addr"); - cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0, - offsetof(CPUPPCState, fpscr), "fpscr"); + cpu_fpscr = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUPPCState, fpscr), "fpscr"); cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUPPCState, access_type), "access_type"); @@ -2302,6 +2302,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT); /* mcrfs */ static void gen_mcrfs(DisasContext *ctx) { + TCGv tmp = tcg_temp_new(); int bfa; if (unlikely(!ctx->fpu_enabled)) { @@ -2309,9 +2310,11 @@ static void gen_mcrfs(DisasContext *ctx) return; } bfa = 4 * (7 - crfS(ctx->opcode)); - tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa); + tcg_gen_shri_tl(tmp, cpu_fpscr, bfa); + tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp); + tcg_temp_free(tmp); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf); - tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa)); + tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa)); } /* mffs */ @@ -2322,7 +2325,7 @@ static void gen_mffs(DisasContext *ctx) return; } gen_reset_fpstatus(); - tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr); + tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr); gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0); } @@ -2346,7 +2349,8 @@ static void gen_mtfsb0(DisasContext *ctx) tcg_temp_free_i32(t0); } if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } } @@ -2371,7 +2375,8 @@ static void gen_mtfsb1(DisasContext *ctx) tcg_temp_free_i32(t0); } if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -2397,7 +2402,8 @@ static void gen_mtfsf(DisasContext *ctx) gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0); tcg_temp_free_i32(t0); if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -2425,7 +2431,8 @@ static void gen_mtfsfi(DisasContext *ctx) tcg_temp_free_i64(t0); tcg_temp_free_i32(t1); if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -9463,7 +9470,7 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf, if ((i & (RFPL - 1)) == (RFPL - 1)) cpu_fprintf(f, "\n"); } - cpu_fprintf(f, "FPSCR %08x\n", env->fpscr); + cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr); #if !defined(CONFIG_USER_ONLY) cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n", |