* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "cpu.h"
-#include "helper.h"
+#include "exec/helper-proto.h"
+#include "exec/cpu_ldst.h"
#include "helper_regs.h"
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
- env->exception_index = POWERPC_EXCP_NONE;
+ cs->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
}
-void ppc_hw_interrupt(CPUPPCState *env)
+static void ppc_hw_interrupt(CPUPPCState *env)
{
- env->exception_index = POWERPC_EXCP_NONE;
+ CPUState *cs = CPU(ppc_env_get_cpu(env));
+
+ cs->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
}
#else /* defined(CONFIG_USER_ONLY) */
*/
static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
{
+ CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- CPUState *cs;
target_ulong msr, new_msr, vector;
int srr0, srr1, asrr0, asrr1;
int lpes0, lpes1, lev;
fprintf(stderr, "Machine check while not allowed. "
"Entering checkstop state\n");
}
- cs = CPU(cpu);
cs->halted = 1;
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
msr |= env->error_code;
goto store_next;
case POWERPC_EXCP_EXTERNAL: /* External input */
+ cs = CPU(cpu);
+
if (lpes0 == 1) {
new_msr |= (target_ulong)MSR_HVB;
}
if (env->mpic_proxy) {
/* IACK the IRQ on delivery */
- env->spr[SPR_BOOKE_EPR] = ldl_phys(env->mpic_iack);
+ env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
}
goto store_next;
case POWERPC_EXCP_ALIGN: /* Alignment exception */
/* Get rS/rD and rA from faulting opcode */
env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
& 0x03FF0000) >> 16;
- goto store_current;
+ goto store_next;
case POWERPC_EXCP_PROGRAM: /* Program exception */
switch (env->error_code & ~0xF) {
case POWERPC_EXCP_FP:
if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
LOG_EXCP("Ignore floating point exception\n");
- env->exception_index = POWERPC_EXCP_NONE;
+ cs->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
return;
}
break;
default:
/* Should never occur */
- cpu_abort(env, "Invalid program exception %d. Aborting\n",
+ cpu_abort(cs, "Invalid program exception %d. Aborting\n",
env->error_code);
break;
}
break;
}
/* XXX: TODO */
- cpu_abort(env, "Debug exception is not implemented yet !\n");
+ cpu_abort(cs, "Debug exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
env->spr[SPR_BOOKE_ESR] = ESR_SPV;
goto store_current;
case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
/* XXX: TODO */
- cpu_abort(env, "Embedded floating point data exception "
+ cpu_abort(cs, "Embedded floating point data exception "
"is not implemented yet !\n");
env->spr[SPR_BOOKE_ESR] = ESR_SPV;
goto store_next;
case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
/* XXX: TODO */
- cpu_abort(env, "Embedded floating point round exception "
+ cpu_abort(cs, "Embedded floating point round exception "
"is not implemented yet !\n");
env->spr[SPR_BOOKE_ESR] = ESR_SPV;
goto store_next;
case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
/* XXX: TODO */
- cpu_abort(env,
+ cpu_abort(cs,
"Performance counter exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
new_msr |= (target_ulong)MSR_HVB;
}
goto store_current;
+ case POWERPC_EXCP_FU: /* Facility unavailable exception */
+ if (lpes1 == 0) {
+ new_msr |= (target_ulong)MSR_HVB;
+ }
+ goto store_current;
case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
LOG_EXCP("PIT exception\n");
goto store_next;
case POWERPC_EXCP_IO: /* IO error exception */
/* XXX: TODO */
- cpu_abort(env, "601 IO error exception is not implemented yet !\n");
+ cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_RUNM: /* Run mode exception */
/* XXX: TODO */
- cpu_abort(env, "601 run mode exception is not implemented yet !\n");
+ cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_EMUL: /* Emulation trap exception */
/* XXX: TODO */
- cpu_abort(env, "602 emulation trap exception "
+ cpu_abort(cs, "602 emulation trap exception "
"is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
case POWERPC_EXCP_74xx:
goto tlb_miss_74xx;
default:
- cpu_abort(env, "Invalid instruction TLB miss exception\n");
+ cpu_abort(cs, "Invalid instruction TLB miss exception\n");
break;
}
break;
case POWERPC_EXCP_74xx:
goto tlb_miss_74xx;
default:
- cpu_abort(env, "Invalid data load TLB miss exception\n");
+ cpu_abort(cs, "Invalid data load TLB miss exception\n");
break;
}
break;
msr |= env->error_code; /* key bit */
break;
default:
- cpu_abort(env, "Invalid data store TLB miss exception\n");
+ cpu_abort(cs, "Invalid data store TLB miss exception\n");
break;
}
goto store_next;
case POWERPC_EXCP_FPA: /* Floating-point assist exception */
/* XXX: TODO */
- cpu_abort(env, "Floating point assist exception "
+ cpu_abort(cs, "Floating point assist exception "
"is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_DABR: /* Data address breakpoint */
/* XXX: TODO */
- cpu_abort(env, "DABR exception is not implemented yet !\n");
+ cpu_abort(cs, "DABR exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
/* XXX: TODO */
- cpu_abort(env, "IABR exception is not implemented yet !\n");
+ cpu_abort(cs, "IABR exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_SMI: /* System management interrupt */
/* XXX: TODO */
- cpu_abort(env, "SMI exception is not implemented yet !\n");
+ cpu_abort(cs, "SMI exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_THERM: /* Thermal interrupt */
/* XXX: TODO */
- cpu_abort(env, "Thermal management exception "
+ cpu_abort(cs, "Thermal management exception "
"is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
new_msr |= (target_ulong)MSR_HVB;
}
/* XXX: TODO */
- cpu_abort(env,
+ cpu_abort(cs,
"Performance counter exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_VPUA: /* Vector assist exception */
/* XXX: TODO */
- cpu_abort(env, "VPU assist exception is not implemented yet !\n");
+ cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_SOFTP: /* Soft patch exception */
/* XXX: TODO */
- cpu_abort(env,
+ cpu_abort(cs,
"970 soft-patch exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_MAINT: /* Maintenance exception */
/* XXX: TODO */
- cpu_abort(env,
+ cpu_abort(cs,
"970 maintenance exception is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
/* XXX: TODO */
- cpu_abort(env, "Maskable external exception "
+ cpu_abort(cs, "Maskable external exception "
"is not implemented yet !\n");
goto store_next;
case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
/* XXX: TODO */
- cpu_abort(env, "Non maskable external exception "
+ cpu_abort(cs, "Non maskable external exception "
"is not implemented yet !\n");
goto store_next;
default:
excp_invalid:
- cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
+ cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
break;
store_current:
/* save current instruction location */
if (asrr1 != -1) {
env->spr[asrr1] = env->spr[srr1];
}
- /* If we disactivated any translation, flush TLBs */
- if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
- tlb_flush(env, 1);
+
+ if (env->spr[SPR_LPCR] & LPCR_AIL) {
+ new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
+ } else if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
+ /* If we disactivated any translation, flush TLBs */
+ tlb_flush(cs, 1);
}
#ifdef TARGET_PPC64
/* Jump to handler */
vector = env->excp_vectors[excp];
if (vector == (target_ulong)-1ULL) {
- cpu_abort(env, "Raised an exception without defined vector %d\n",
+ cpu_abort(cs, "Raised an exception without defined vector %d\n",
excp);
}
vector |= env->excp_prefix;
hreg_compute_hflags(env);
env->nip = vector;
/* Reset exception state */
- env->exception_index = POWERPC_EXCP_NONE;
+ cs->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
/* XXX: The BookE changes address space when switching modes,
we should probably implement that as different MMU indexes,
but for the moment we do it the slow way and flush all. */
- tlb_flush(env, 1);
+ tlb_flush(cs, 1);
}
}
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
- powerpc_excp(cpu, env->excp_model, env->exception_index);
+ powerpc_excp(cpu, env->excp_model, cs->exception_index);
}
-void ppc_hw_interrupt(CPUPPCState *env)
+static void ppc_hw_interrupt(CPUPPCState *env)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
int hdice;
if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
/* Hypervisor decrementer exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
- env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
return;
}
}
/* Decrementer exception */
if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
- env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
+ if (ppc_decr_clear_on_delivery(env)) {
+ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
+ }
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
return;
}
}
}
}
+
+void ppc_cpu_do_system_reset(CPUState *cs)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+
+ powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
+}
#endif /* !CONFIG_USER_ONLY */
+bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ ppc_hw_interrupt(env);
+ if (env->pending_interrupts == 0) {
+ cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ }
+ return true;
+ }
+ return false;
+}
+
#if defined(DEBUG_OP)
static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
{
void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
uint32_t error_code)
{
+ CPUState *cs = CPU(ppc_env_get_cpu(env));
+
#if 0
printf("Raise exception %3x code : %d\n", exception, error_code);
#endif
- env->exception_index = exception;
+ cs->exception_index = exception;
env->error_code = error_code;
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
}
void helper_raise_exception(CPUPPCState *env, uint32_t exception)