summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/powerpc/ppc602.inc
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/powerpc/ppc602.inc')
-rw-r--r--src/devices/cpu/powerpc/ppc602.inc279
1 files changed, 279 insertions, 0 deletions
diff --git a/src/devices/cpu/powerpc/ppc602.inc b/src/devices/cpu/powerpc/ppc602.inc
new file mode 100644
index 00000000000..6b1998201f7
--- /dev/null
+++ b/src/devices/cpu/powerpc/ppc602.inc
@@ -0,0 +1,279 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+static void ppc_dsa(UINT32 op)
+{
+ UINT32 msr = ppc_get_msr();
+
+ msr &= ~(MSR_SA | MSR_EE | MSR_PR | MSR_AP);
+ if (ppc.esasrr & 0x8) msr |= MSR_PR;
+ if (ppc.esasrr & 0x4) msr |= MSR_AP;
+ if (ppc.esasrr & 0x2) msr |= MSR_SA;
+ if (ppc.esasrr & 0x1) msr |= MSR_EE;
+
+ ppc_set_msr(msr);
+}
+
+static void ppc_esa(UINT32 op)
+{
+ int sa, ee, pr, ap;
+ UINT32 msr = ppc_get_msr();
+
+ sa = (msr & MSR_SA) ? 1 : 0;
+ ee = (msr & MSR_EE) ? 1 : 0;
+ pr = (msr & MSR_PR) ? 1 : 0;
+ ap = (msr & MSR_AP) ? 1 : 0;
+
+ ppc.esasrr = (pr << 3) | (ap << 2) | (sa << 1) | (ee);
+
+ msr &= ~(MSR_EE | MSR_PR | MSR_AP);
+ msr |= MSR_SA;
+
+ ppc_set_msr(msr);
+}
+
+#ifndef PPC_DRC
+static void ppc_tlbli(UINT32 op)
+{
+}
+
+static void ppc_tlbld(UINT32 op)
+{
+}
+#endif
+
+#ifndef PPC_DRC
+void ppc602_exception(int exception)
+{
+ switch( exception )
+ {
+ case EXCEPTION_IRQ: /* External Interrupt */
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0500;
+ else
+ ppc.npc = ppc.ibr | 0x0500;
+
+ ppc.interrupt_pending &= ~0x1;
+ }
+ break;
+
+ case EXCEPTION_DECREMENTER: /* Decrementer overflow exception */
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0900;
+ else
+ ppc.npc = ppc.ibr | 0x0900;
+
+ ppc.interrupt_pending &= ~0x2;
+ }
+ break;
+
+ case EXCEPTION_TRAP: /* Program exception / Trap */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.pc;
+ SRR1 = (msr & 0xff73) | 0x20000; /* 0x20000 = TRAP bit */
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0700;
+ else
+ ppc.npc = ppc.ibr | 0x0700;
+ }
+ break;
+
+ case EXCEPTION_SYSTEM_CALL: /* System call */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = (msr & 0xff73);
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0c00;
+ else
+ ppc.npc = ppc.ibr | 0x0c00;
+ }
+ break;
+
+ case EXCEPTION_SMI:
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x1400;
+ else
+ ppc.npc = ppc.ibr | 0x1400;
+
+ ppc.interrupt_pending &= ~0x4;
+ }
+ break;
+
+
+ default:
+ fatalerror("ppc: Unhandled exception %d\n", exception);
+ break;
+ }
+}
+
+static void ppc602_set_irq_line(int irqline, int state)
+{
+ if( state ) {
+ ppc.interrupt_pending |= 0x1;
+ if (ppc.irq_callback)
+ {
+ ppc.irq_callback(ppc.device, irqline);
+ }
+ }
+}
+
+static void ppc602_set_smi_line(int state)
+{
+ if( state ) {
+ ppc.interrupt_pending |= 0x4;
+ }
+}
+
+INLINE void ppc602_check_interrupts(void)
+{
+ if (MSR & MSR_EE)
+ {
+ if (ppc.interrupt_pending != 0)
+ {
+ if (ppc.interrupt_pending & 0x1)
+ {
+ ppc602_exception(EXCEPTION_IRQ);
+ }
+ else if (ppc.interrupt_pending & 0x2)
+ {
+ ppc602_exception(EXCEPTION_DECREMENTER);
+ }
+ else if (ppc.interrupt_pending & 0x4)
+ {
+ ppc602_exception(EXCEPTION_SMI);
+ }
+ }
+ }
+}
+
+static CPU_RESET( ppc602 )
+{
+ ppc.pc = ppc.npc = 0xfff00100;
+
+ ppc_set_msr(0x40);
+
+ ppc.hid0 = 1;
+
+ ppc.interrupt_pending = 0;
+}
+
+static CPU_EXECUTE( ppc602 )
+{
+ int exception_type;
+ UINT32 opcode;
+ ppc_tb_base_icount = ppc_icount;
+ ppc_dec_base_icount = ppc_icount;
+
+ // check if decrementer exception occurs during execution
+ if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
+ {
+ ppc_dec_trigger_cycle = ppc_icount - DEC;
+ }
+ else
+ {
+ ppc_dec_trigger_cycle = 0x7fffffff;
+ }
+
+ // MinGW's optimizer kills setjmp()/longjmp()
+ SETJMP_GNUC_PROTECT();
+
+ exception_type = setjmp(ppc.exception_jmpbuf);
+ if (exception_type)
+ {
+ ppc.npc = ppc.pc;
+ ppc602_exception(exception_type);
+ }
+
+ while( ppc_icount > 0 )
+ {
+ ppc.pc = ppc.npc;
+ debugger_instruction_hook(device, ppc.pc);
+
+ if (MSR & MSR_IR)
+ opcode = ppc_readop_translated(ppc.program, ppc.pc);
+ else
+ opcode = ROPCODE64(ppc.pc);
+
+ ppc.npc = ppc.pc + 4;
+ switch(opcode >> 26)
+ {
+ case 19: ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
+ case 31: ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
+ case 59: ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
+ case 63: ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
+ default: ppc.optable[opcode >> 26](opcode); break;
+ }
+
+ ppc_icount--;
+
+ if(ppc_icount == ppc_dec_trigger_cycle) {
+ ppc.interrupt_pending |= 0x2;
+ }
+
+ ppc602_check_interrupts();
+ }
+
+ // update timebase
+ // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
+ ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
+
+ // update decrementer
+ DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
+}
+#endif // PPC_DRC