Embedded PowerPC Device Control Registers infrastructure.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2653 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
j_mayer 2007-04-12 21:11:03 +00:00
parent 83b1fb88f8
commit 2e719ba347
4 changed files with 117 additions and 7 deletions

View File

@ -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) */

View File

@ -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"

View File

@ -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)

7
vl.h
View File

@ -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);