diff options
-rw-r--r-- | hw/ppc.c | 95 | ||||
-rw-r--r-- | target-ppc/cpu.h | 6 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 16 | ||||
-rw-r--r-- | vl.h | 7 |
4 files changed, 117 insertions, 7 deletions
@@ -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) @@ -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); |