aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ppc.c95
-rw-r--r--target-ppc/cpu.h6
-rw-r--r--target-ppc/op_helper.c16
-rw-r--r--vl.h7
4 files changed, 117 insertions, 7 deletions
diff --git a/hw/ppc.c b/hw/ppc.c
index f5c4500..f502271 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -547,6 +547,101 @@ void ppc_emb_timers_init (CPUState *env)
}
}
+/*****************************************************************************/
+/* Embedded PowerPC Device Control Registers */
+typedef struct ppc_dcrn_t ppc_dcrn_t;
+struct ppc_dcrn_t {
+ dcr_read_cb dcr_read;
+ dcr_write_cb dcr_write;
+ void *opaque;
+};
+
+#define DCRN_NB 1024
+struct ppc_dcr_t {
+ ppc_dcrn_t dcrn[DCRN_NB];
+ int (*read_error)(int dcrn);
+ int (*write_error)(int dcrn);
+};
+
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
+{
+ ppc_dcrn_t *dcr;
+
+ if (dcrn < 0 || dcrn >= DCRN_NB)
+ goto error;
+ dcr = &dcr_env->dcrn[dcrn];
+ if (dcr->dcr_read == NULL)
+ goto error;
+ *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
+
+ return 0;
+
+ error:
+ if (dcr_env->read_error != NULL)
+ return (*dcr_env->read_error)(dcrn);
+
+ return -1;
+}
+
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
+{
+ ppc_dcrn_t *dcr;
+
+ if (dcrn < 0 || dcrn >= DCRN_NB)
+ goto error;
+ dcr = &dcr_env->dcrn[dcrn];
+ if (dcr->dcr_write == NULL)
+ goto error;
+ (*dcr->dcr_write)(dcr->opaque, dcrn, val);
+
+ return 0;
+
+ error:
+ if (dcr_env->write_error != NULL)
+ return (*dcr_env->write_error)(dcrn);
+
+ return -1;
+}
+
+int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
+ dcr_read_cb dcr_read, dcr_write_cb dcr_write)
+{
+ ppc_dcr_t *dcr_env;
+ ppc_dcrn_t *dcr;
+
+ dcr_env = env->dcr_env;
+ if (dcr_env == NULL)
+ return -1;
+ if (dcrn < 0 || dcrn >= DCRN_NB)
+ return -1;
+ dcr = &dcr_env->dcrn[dcrn];
+ if (dcr->opaque != NULL ||
+ dcr->dcr_read != NULL ||
+ dcr->dcr_write != NULL)
+ return -1;
+ dcr->opaque = opaque;
+ dcr->dcr_read = dcr_read;
+ dcr->dcr_write = dcr_write;
+
+ return 0;
+}
+
+int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
+ int (*write_error)(int dcrn))
+{
+ ppc_dcr_t *dcr_env;
+
+ dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
+ if (dcr_env == NULL)
+ return -1;
+ dcr_env->read_error = read_error;
+ dcr_env->write_error = write_error;
+ env->dcr_env = dcr_env;
+
+ return 0;
+}
+
+
#if 0
/*****************************************************************************/
/* Handle system reset (for now, just stop emulation) */
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 0560a38..2a2c440 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -730,8 +730,6 @@ struct CPUPPCState {
/* Time base and decrementer */
ppc_tb_t *tb_env;
/* Device control registers */
- int (*dcr_read)(ppc_dcr_t *dcr_env, int dcr_num, target_ulong *val);
- int (*dcr_write)(ppc_dcr_t *dcr_env, int dcr_num, target_ulong val);
ppc_dcr_t *dcr_env;
/* PowerPC TLB registers (for 4xx and 60x software driven TLBs) */
@@ -863,6 +861,10 @@ void store_booke_tsr (CPUPPCState *env, target_ulong val);
#endif
#endif
+/* Device control registers */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp);
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
+
#define TARGET_PAGE_BITS 12
#include "cpu-all.h"
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index e1fff7f..a65da36 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1249,20 +1249,26 @@ void do_load_dcr (void)
{
target_ulong val;
- if (unlikely(env->dcr_read == NULL))
+ if (unlikely(env->dcr_env == NULL)) {
+ printf("No DCR environment\n");
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
- else if (unlikely((*env->dcr_read)(env->dcr_env, T0, &val) != 0))
+ } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
+ printf("DCR read error\n");
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
- else
+ } else {
T0 = val;
+ }
}
void do_store_dcr (void)
{
- if (unlikely(env->dcr_write == NULL))
+ if (unlikely(env->dcr_env == NULL)) {
+ printf("No DCR environment\n");
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL);
- else if (unlikely((*env->dcr_write)(env->dcr_env, T0, T1) != 0))
+ } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
+ printf("DCR write error\n");
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG);
+ }
}
void do_load_403_pb (int num)
diff --git a/vl.h b/vl.h
index b40ff37..df76a9f 100644
--- a/vl.h
+++ b/vl.h
@@ -1147,6 +1147,13 @@ extern QEMUMachine shix_machine;
#ifdef TARGET_PPC
/* PowerPC hardware exceptions management helpers */
ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq);
+/* Embedded PowerPC DCR management */
+typedef target_ulong (*dcr_read_cb)(void *opaque, int dcrn);
+typedef void (*dcr_write_cb)(void *opaque, int dcrn, target_ulong val);
+int ppc_dcr_init (CPUState *env, int (*dcr_read_error)(int dcrn),
+ int (*dcr_write_error)(int dcrn));
+int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
+ dcr_read_cb drc_read, dcr_write_cb dcr_write);
#endif
void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val);