Add bus model (or input pins) into PowerPC CPU flags.
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 16 Apr 2007 07:34:39 +0000 (07:34 +0000)
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 16 Apr 2007 07:34:39 +0000 (07:34 +0000)
Add PowerPC 970 bus and exceptions model.
Add code provision for PowerPC 970 instanciation.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2680 c046a42c-6fe2-441c-8c8c-71466251a162

hw/ppc.c
target-ppc/cpu.h
target-ppc/helper.c
target-ppc/translate_init.c

index b16f305..62e9e1b 100644 (file)
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -161,6 +161,128 @@ void ppc6xx_irq_init (CPUState *env)
     env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env, 6);
 }
 
+/* PowerPC 970 internal IRQ controller */
+static void ppc970_set_irq (void *opaque, int pin, int level)
+{
+    CPUState *env = opaque;
+    int cur_level;
+
+#if defined(PPC_DEBUG_IRQ)
+    if (loglevel & CPU_LOG_INT) {
+        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
+                env, pin, level);
+    }
+#endif
+    cur_level = (env->irq_input_state >> pin) & 1;
+    /* Don't generate spurious events */
+    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
+        switch (pin) {
+        case PPC970_INPUT_INT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the external IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
+            break;
+        case PPC970_INPUT_THINT:
+            /* Level sensitive - active high */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
+                        level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
+            break;
+        case PPC970_INPUT_MCP:
+            /* Negative edge sensitive */
+            /* XXX: TODO: actual reaction may depends on HID0 status
+             *            603/604/740/750: check HID0[EMCP]
+             */
+            if (cur_level == 1 && level == 0) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: raise machine check state\n",
+                            __func__);
+                }
+#endif
+                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
+            }
+            break;
+        case PPC970_INPUT_CKSTP:
+            /* Level sensitive - active low */
+            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
+            if (level) {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: stop the CPU\n", __func__);
+                }
+#endif
+                env->halted = 1;
+            } else {
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: restart the CPU\n", __func__);
+                }
+#endif
+                env->halted = 0;
+            }
+            break;
+        case PPC970_INPUT_HRESET:
+            /* Level sensitive - active low */
+            if (level) {
+#if 0 // XXX: TOFIX
+#if defined(PPC_DEBUG_IRQ)
+                if (loglevel & CPU_LOG_INT) {
+                    fprintf(logfile, "%s: reset the CPU\n", __func__);
+                }
+#endif
+                cpu_reset(env);
+#endif
+            }
+            break;
+        case PPC970_INPUT_SRESET:
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
+                        __func__, level);
+            }
+#endif
+            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
+            break;
+        case PPC970_INPUT_TBEN:
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
+                        level);
+            }
+#endif
+            /* XXX: TODO */
+            break;
+        default:
+            /* Unknown pin - do nothing */
+#if defined(PPC_DEBUG_IRQ)
+            if (loglevel & CPU_LOG_INT) {
+                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
+            }
+#endif
+            return;
+        }
+        if (level)
+            env->irq_input_state |= 1 << pin;
+        else
+            env->irq_input_state &= ~(1 << pin);
+    }
+}
+
+void ppc970_irq_init (CPUState *env)
+{
+    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env, 7);
+}
+
 /* PowerPC 405 internal IRQ controller */
 static void ppc405_set_irq (void *opaque, int pin, int level)
 {
index 740bc1b..1e309f9 100644 (file)
@@ -393,51 +393,60 @@ enum {
 /* CPU run-time flags (MMU and exception model) */
 enum {
     /* MMU model */
-    PPC_FLAGS_MMU_MASK     = 0x0000000F,
+    PPC_FLAGS_MMU_MASK       = 0x000000FF,
     /* Standard 32 bits PowerPC MMU */
-    PPC_FLAGS_MMU_32B      = 0x00000000,
+    PPC_FLAGS_MMU_32B        = 0x00000000,
     /* Standard 64 bits PowerPC MMU */
-    PPC_FLAGS_MMU_64B      = 0x00000001,
+    PPC_FLAGS_MMU_64B        = 0x00000001,
     /* PowerPC 601 MMU */
-    PPC_FLAGS_MMU_601      = 0x00000002,
+    PPC_FLAGS_MMU_601        = 0x00000002,
     /* PowerPC 6xx MMU with software TLB */
-    PPC_FLAGS_MMU_SOFT_6xx = 0x00000003,
+    PPC_FLAGS_MMU_SOFT_6xx   = 0x00000003,
     /* PowerPC 4xx MMU with software TLB */
-    PPC_FLAGS_MMU_SOFT_4xx = 0x00000004,
+    PPC_FLAGS_MMU_SOFT_4xx   = 0x00000004,
     /* PowerPC 403 MMU */
-    PPC_FLAGS_MMU_403      = 0x00000005,
-    /* Freescale e500 MMU model */
-    PPC_FLAGS_MMU_e500     = 0x00000006,
+    PPC_FLAGS_MMU_403        = 0x00000005,
+    /* BookE FSL MMU model */
+    PPC_FLAGS_MMU_BOOKE_FSL  = 0x00000006,
     /* BookE MMU model */
-    PPC_FLAGS_MMU_BOOKE    = 0x00000007,
+    PPC_FLAGS_MMU_BOOKE      = 0x00000007,
+    /* 64 bits "bridge" PowerPC MMU */
+    PPC_FLAGS_MMU_64BRIDGE   = 0x00000008,
     /* Exception model */
-    PPC_FLAGS_EXCP_MASK    = 0x000000F0,
+    PPC_FLAGS_EXCP_MASK      = 0x0000FF00,
     /* Standard PowerPC exception model */
-    PPC_FLAGS_EXCP_STD     = 0x00000000,
+    PPC_FLAGS_EXCP_STD       = 0x00000000,
     /* PowerPC 40x exception model */
-    PPC_FLAGS_EXCP_40x     = 0x00000010,
+    PPC_FLAGS_EXCP_40x       = 0x00000100,
     /* PowerPC 601 exception model */
-    PPC_FLAGS_EXCP_601     = 0x00000020,
+    PPC_FLAGS_EXCP_601       = 0x00000200,
     /* PowerPC 602 exception model */
-    PPC_FLAGS_EXCP_602     = 0x00000030,
+    PPC_FLAGS_EXCP_602       = 0x00000300,
     /* PowerPC 603 exception model */
-    PPC_FLAGS_EXCP_603     = 0x00000040,
+    PPC_FLAGS_EXCP_603       = 0x00000400,
     /* PowerPC 604 exception model */
-    PPC_FLAGS_EXCP_604     = 0x00000050,
+    PPC_FLAGS_EXCP_604       = 0x00000500,
     /* PowerPC 7x0 exception model */
-    PPC_FLAGS_EXCP_7x0     = 0x00000060,
+    PPC_FLAGS_EXCP_7x0       = 0x00000600,
     /* PowerPC 7x5 exception model */
-    PPC_FLAGS_EXCP_7x5     = 0x00000070,
+    PPC_FLAGS_EXCP_7x5       = 0x00000700,
     /* PowerPC 74xx exception model */
-    PPC_FLAGS_EXCP_74xx    = 0x00000080,
+    PPC_FLAGS_EXCP_74xx      = 0x00000800,
     /* PowerPC 970 exception model */
-    PPC_FLAGS_EXCP_970     = 0x00000090,
+    PPC_FLAGS_EXCP_970       = 0x00000900,
     /* BookE exception model */
-    PPC_FLAGS_EXCP_BOOKE   = 0x000000A0,
+    PPC_FLAGS_EXCP_BOOKE     = 0x00000A00,
+    /* Input pins model */
+    PPC_FLAGS_INPUT_MASK     = 0x000F0000,
+    PPC_FLAGS_INPUT_6xx      = 0x00000000,
+    PPC_FLAGS_INPUT_BookE    = 0x00010000,
+    PPC_FLAGS_INPUT_40x      = 0x00020000,
+    PPC_FLAGS_INPUT_970      = 0x00030000,
 };
 
 #define PPC_MMU(env) (env->flags & PPC_FLAGS_MMU_MASK)
 #define PPC_EXCP(env) (env->flags & PPC_FLAGS_EXCP_MASK)
+#define PPC_INPUT(env) (env->flags & PPC_FLAGS_INPUT_MASK)
 
 /*****************************************************************************/
 /* Supported instruction set definitions */
@@ -454,64 +463,78 @@ enum {
 #define PPC_INSNS_403 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO |         \
                        PPC_MEM_TLBIA | PPC_4xx_COMMON | PPC_40x_EXCP |        \
                        PPC_40x_SPEC)
-#define PPC_FLAGS_403 (PPC_FLAGS_MMU_403 | PPC_FLAGS_EXCP_40x)
+#define PPC_FLAGS_403 (PPC_FLAGS_MMU_403 | PPC_FLAGS_EXCP_40x |               \
+                       PPC_FLAGS_INPUT_40x)
 /* PowerPC 405 */
 #define PPC_INSNS_405 (PPC_INSNS_EMB | PPC_MEM_SYNC | PPC_MEM_EIEIO |         \
                        PPC_CACHE_OPT | PPC_MEM_TLBIA | PPC_TB |               \
                        PPC_4xx_COMMON | PPC_40x_SPEC |  PPC_40x_EXCP |        \
                        PPC_405_MAC)
-#define PPC_FLAGS_405 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x)
+#define PPC_FLAGS_405 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x |          \
+                       PPC_FLAGS_INPUT_40x)
 /* PowerPC 440 */
 #define PPC_INSNS_440 (PPC_INSNS_EMB | PPC_CACHE_OPT | PPC_BOOKE |            \
                        PPC_4xx_COMMON | PPC_405_MAC | PPC_440_SPEC)
-#define PPC_FLAGS_440 (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE)
+#define PPC_FLAGS_440 (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE |           \
+                       PPC_FLAGS_INPUT_BookE)
 /* Generic BookE PowerPC */
 #define PPC_INSNS_BOOKE (PPC_INSNS_EMB | PPC_BOOKE | PPC_MEM_EIEIO |          \
                          PPC_FLOAT | PPC_FLOAT_OPT | PPC_CACHE_OPT)
-#define PPC_FLAGS_BOOKE (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE)
+#define PPC_FLAGS_BOOKE (PPC_FLAGS_MMU_BOOKE | PPC_FLAGS_EXCP_BOOKE |         \
+                         PPC_FLAGS_INPUT_BookE)
 /* e500 core */
 #define PPC_INSNS_E500 (PPC_INSNS_EMB | PPC_BOOKE | PPC_MEM_EIEIO |           \
                         PPC_CACHE_OPT | PPC_E500_VECTOR)
-#define PPC_FLAGS_E500 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x)
+#define PPC_FLAGS_E500 (PPC_FLAGS_MMU_SOFT_4xx | PPC_FLAGS_EXCP_40x |         \
+                        PPC_FLAGS_INPUT_BookE)
 /* Non-embedded PowerPC */
 #define PPC_INSNS_COMMON  (PPC_INSNS_BASE | PPC_FLOAT | PPC_MEM_SYNC |        \
-                            PPC_MEM_EIEIO | PPC_SEGMENT | PPC_MEM_TLBIE)
+                           PPC_MEM_EIEIO | PPC_SEGMENT | PPC_MEM_TLBIE)
 /* PowerPC 601 */
 #define PPC_INSNS_601 (PPC_INSNS_COMMON | PPC_EXTERN | PPC_POWER_BR)
-#define PPC_FLAGS_601 (PPC_FLAGS_MMU_601 | PPC_FLAGS_EXCP_601)
+#define PPC_FLAGS_601 (PPC_FLAGS_MMU_601 | PPC_FLAGS_EXCP_601 |               \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 602 */
 #define PPC_INSNS_602 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB |       \
                        PPC_MEM_TLBSYNC | PPC_TB | PPC_602_SPEC)
-#define PPC_FLAGS_602 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_602)
+#define PPC_FLAGS_602 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_602 |          \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 603 */
 #define PPC_INSNS_603 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB |       \
                        PPC_MEM_TLBSYNC | PPC_EXTERN | PPC_TB)
-#define PPC_FLAGS_603 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603)
+#define PPC_FLAGS_603 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603 |          \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC G2 */
 #define PPC_INSNS_G2 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_6xx_TLB |        \
                       PPC_MEM_TLBSYNC | PPC_EXTERN | PPC_TB)
-#define PPC_FLAGS_G2 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603)
+#define PPC_FLAGS_G2 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_603 |           \
+                      PPC_FLAGS_INPUT_6xx)
 /* PowerPC 604 */
 #define PPC_INSNS_604 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN |        \
                        PPC_MEM_TLBSYNC | PPC_TB)
-#define PPC_FLAGS_604 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_604)
+#define PPC_FLAGS_604 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_604 |               \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 740/750 (aka G3) */
 #define PPC_INSNS_7x0 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN |        \
                        PPC_MEM_TLBSYNC | PPC_TB)
-#define PPC_FLAGS_7x0 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_7x0)
+#define PPC_FLAGS_7x0 (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_7x0 |               \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 745/755 */
 #define PPC_INSNS_7x5 (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_EXTERN |        \
                        PPC_MEM_TLBSYNC | PPC_TB | PPC_6xx_TLB)
-#define PPC_FLAGS_7x5 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_7x5)
+#define PPC_FLAGS_7x5 (PPC_FLAGS_MMU_SOFT_6xx | PPC_FLAGS_EXCP_7x5 |          \
+                       PPC_FLAGS_INPUT_6xx)
 /* PowerPC 74xx (aka G4) */
 #define PPC_INSNS_74xx (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_ALTIVEC |      \
                         PPC_MEM_TLBSYNC | PPC_TB)
-#define PPC_FLAGS_74xx (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_74xx)
+#define PPC_FLAGS_74xx (PPC_FLAGS_MMU_32B | PPC_FLAGS_EXCP_74xx |             \
+                        PPC_FLAGS_INPUT_6xx)
 /* PowerPC 970 (aka G5) */
 #define PPC_INSNS_970  (PPC_INSNS_COMMON | PPC_FLOAT_EXT | PPC_FLOAT_OPT |    \
                         PPC_ALTIVEC | PPC_MEM_TLBSYNC | PPC_TB |              \
                         PPC_64B | PPC_64_BRIDGE | PPC_SLBI)
-#define PPC_FLAGS_970  (PPC_FLAGS_MMU_64B | PPC_FLAGS_EXCP_970)
+#define PPC_FLAGS_970  (PPC_FLAGS_MMU_64BRIDGE | PPC_FLAGS_EXCP_970 |         \
+                        PPC_FLAGS_INPUT_970)
 
 /* Default PowerPC will be 604/970 */
 #define PPC_INSNS_PPC32 PPC_INSNS_604
@@ -1347,6 +1370,17 @@ enum {
     PPC405_INPUT_DEBUG      = 6,
 };
 
+enum {
+    /* PowerPC 970 input pins */
+    PPC970_INPUT_HRESET     = 0,
+    PPC970_INPUT_SRESET     = 1,
+    PPC970_INPUT_CKSTP      = 2,
+    PPC970_INPUT_TBEN       = 3,
+    PPC970_INPUT_MCP        = 4,
+    PPC970_INPUT_INT        = 5,
+    PPC970_INPUT_THINT      = 6,
+};
+
 /* Hardware exceptions definitions */
 enum {
     /* External hardware exception sources */
@@ -1356,12 +1390,13 @@ enum {
     PPC_INTERRUPT_SMI    = 3,  /* System management interrupt          */
     PPC_INTERRUPT_CEXT   = 4,  /* Critical external interrupt          */
     PPC_INTERRUPT_DEBUG  = 5,  /* External debug exception             */
+    PPC_INTERRUPT_THERM  = 6,  /* Thermal exception                    */
     /* Internal hardware exception sources */
-    PPC_INTERRUPT_DECR   = 6,  /* Decrementer exception                */
-    PPC_INTERRUPT_HDECR  = 7,  /* Hypervisor decrementer exception     */
-    PPC_INTERRUPT_PIT    = 8,  /* Programmable inteval timer interrupt */
-    PPC_INTERRUPT_FIT    = 9,  /* Fixed interval timer interrupt       */
-    PPC_INTERRUPT_WDT    = 10, /* Watchdog timer interrupt             */
+    PPC_INTERRUPT_DECR   = 7,  /* Decrementer exception                */
+    PPC_INTERRUPT_HDECR  = 8,  /* Hypervisor decrementer exception     */
+    PPC_INTERRUPT_PIT    = 9,  /* Programmable inteval timer interrupt */
+    PPC_INTERRUPT_FIT    = 10, /* Fixed interval timer interrupt       */
+    PPC_INTERRUPT_WDT    = 11, /* Watchdog timer interrupt             */
 };
 
 /*****************************************************************************/
index aac7907..161cc1b 100644 (file)
@@ -2003,6 +2003,13 @@ void ppc_hw_interrupt (CPUPPCState *env)
             env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
 #endif
             raised = 1;
+#if 0 // TODO
+        /* Thermal interrupt */
+        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
+            env->exception_index = EXCP_970_THRM;
+            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
+            raised = 1;
+#endif
         }
 #if 0 // TODO
     /* External debug exception */
index c7a7324..0185123 100644 (file)
@@ -48,6 +48,7 @@ void glue(glue(ppc, name),_irq_init) (CPUPPCState *env);
 #endif
 PPC_IRQ_INIT_FN(405);
 PPC_IRQ_INIT_FN(6xx);
+PPC_IRQ_INIT_FN(970);
 
 /* Generic callbacks:
  * do nothing but store/retrieve spr value
@@ -2350,6 +2351,8 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
     case CPU_PPC_POWER5:  /* Power 5                       */
     case CPU_PPC_POWER5P: /* Power 5+                      */
 #endif
+        break;
+
     case CPU_PPC_970:     /* PowerPC 970                   */
     case CPU_PPC_970FX10: /* PowerPC 970 FX                */
     case CPU_PPC_970FX20:
@@ -2358,12 +2361,41 @@ static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
     case CPU_PPC_970FX31:
     case CPU_PPC_970MP10: /* PowerPC 970 MP                */
     case CPU_PPC_970MP11:
+        gen_spr_generic(env);
+        gen_spr_ne_601(env);
+        /* XXX: not correct */
+        gen_low_BATs(env);
+        /* Time base */
+        gen_tbl(env);
+        gen_spr_7xx(env);
+        /* Hardware implementation registers */
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID0, "HID0",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_HID1, "HID1",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* XXX : not implemented */
+        spr_register(env, SPR_750_HID2, "HID2",
+                     SPR_NOACCESS, SPR_NOACCESS,
+                     &spr_read_generic, &spr_write_generic,
+                     0x00000000);
+        /* Allocate hardware IRQ controller */
+        ppc970_irq_init(env);
+        break;
+
 #if defined (TODO)
     case CPU_PPC_CELL10:  /* Cell family                   */
     case CPU_PPC_CELL20:
     case CPU_PPC_CELL30:
     case CPU_PPC_CELL31:
 #endif
+        break;
+
 #if defined (TODO)
     case CPU_PPC_RS64:    /* Apache (RS64/A35)             */
     case CPU_PPC_RS64II:  /* NorthStar (RS64-II/A50)       */