Commit 2e719ba3476fcf1c7c74649d9e16f486eb8c02fc
1 parent
83b1fb88
Embedded PowerPC Device Control Registers infrastructure.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2653 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
117 additions
and
7 deletions
hw/ppc.c
... | ... | @@ -547,6 +547,101 @@ void ppc_emb_timers_init (CPUState *env) |
547 | 547 | } |
548 | 548 | } |
549 | 549 | |
550 | +/*****************************************************************************/ | |
551 | +/* Embedded PowerPC Device Control Registers */ | |
552 | +typedef struct ppc_dcrn_t ppc_dcrn_t; | |
553 | +struct ppc_dcrn_t { | |
554 | + dcr_read_cb dcr_read; | |
555 | + dcr_write_cb dcr_write; | |
556 | + void *opaque; | |
557 | +}; | |
558 | + | |
559 | +#define DCRN_NB 1024 | |
560 | +struct ppc_dcr_t { | |
561 | + ppc_dcrn_t dcrn[DCRN_NB]; | |
562 | + int (*read_error)(int dcrn); | |
563 | + int (*write_error)(int dcrn); | |
564 | +}; | |
565 | + | |
566 | +int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp) | |
567 | +{ | |
568 | + ppc_dcrn_t *dcr; | |
569 | + | |
570 | + if (dcrn < 0 || dcrn >= DCRN_NB) | |
571 | + goto error; | |
572 | + dcr = &dcr_env->dcrn[dcrn]; | |
573 | + if (dcr->dcr_read == NULL) | |
574 | + goto error; | |
575 | + *valp = (*dcr->dcr_read)(dcr->opaque, dcrn); | |
576 | + | |
577 | + return 0; | |
578 | + | |
579 | + error: | |
580 | + if (dcr_env->read_error != NULL) | |
581 | + return (*dcr_env->read_error)(dcrn); | |
582 | + | |
583 | + return -1; | |
584 | +} | |
585 | + | |
586 | +int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val) | |
587 | +{ | |
588 | + ppc_dcrn_t *dcr; | |
589 | + | |
590 | + if (dcrn < 0 || dcrn >= DCRN_NB) | |
591 | + goto error; | |
592 | + dcr = &dcr_env->dcrn[dcrn]; | |
593 | + if (dcr->dcr_write == NULL) | |
594 | + goto error; | |
595 | + (*dcr->dcr_write)(dcr->opaque, dcrn, val); | |
596 | + | |
597 | + return 0; | |
598 | + | |
599 | + error: | |
600 | + if (dcr_env->write_error != NULL) | |
601 | + return (*dcr_env->write_error)(dcrn); | |
602 | + | |
603 | + return -1; | |
604 | +} | |
605 | + | |
606 | +int ppc_dcr_register (CPUState *env, int dcrn, void *opaque, | |
607 | + dcr_read_cb dcr_read, dcr_write_cb dcr_write) | |
608 | +{ | |
609 | + ppc_dcr_t *dcr_env; | |
610 | + ppc_dcrn_t *dcr; | |
611 | + | |
612 | + dcr_env = env->dcr_env; | |
613 | + if (dcr_env == NULL) | |
614 | + return -1; | |
615 | + if (dcrn < 0 || dcrn >= DCRN_NB) | |
616 | + return -1; | |
617 | + dcr = &dcr_env->dcrn[dcrn]; | |
618 | + if (dcr->opaque != NULL || | |
619 | + dcr->dcr_read != NULL || | |
620 | + dcr->dcr_write != NULL) | |
621 | + return -1; | |
622 | + dcr->opaque = opaque; | |
623 | + dcr->dcr_read = dcr_read; | |
624 | + dcr->dcr_write = dcr_write; | |
625 | + | |
626 | + return 0; | |
627 | +} | |
628 | + | |
629 | +int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn), | |
630 | + int (*write_error)(int dcrn)) | |
631 | +{ | |
632 | + ppc_dcr_t *dcr_env; | |
633 | + | |
634 | + dcr_env = qemu_mallocz(sizeof(ppc_dcr_t)); | |
635 | + if (dcr_env == NULL) | |
636 | + return -1; | |
637 | + dcr_env->read_error = read_error; | |
638 | + dcr_env->write_error = write_error; | |
639 | + env->dcr_env = dcr_env; | |
640 | + | |
641 | + return 0; | |
642 | +} | |
643 | + | |
644 | + | |
550 | 645 | #if 0 |
551 | 646 | /*****************************************************************************/ |
552 | 647 | /* Handle system reset (for now, just stop emulation) */ | ... | ... |
target-ppc/cpu.h
... | ... | @@ -730,8 +730,6 @@ struct CPUPPCState { |
730 | 730 | /* Time base and decrementer */ |
731 | 731 | ppc_tb_t *tb_env; |
732 | 732 | /* Device control registers */ |
733 | - int (*dcr_read)(ppc_dcr_t *dcr_env, int dcr_num, target_ulong *val); | |
734 | - int (*dcr_write)(ppc_dcr_t *dcr_env, int dcr_num, target_ulong val); | |
735 | 733 | ppc_dcr_t *dcr_env; |
736 | 734 | |
737 | 735 | /* PowerPC TLB registers (for 4xx and 60x software driven TLBs) */ |
... | ... | @@ -863,6 +861,10 @@ void store_booke_tsr (CPUPPCState *env, target_ulong val); |
863 | 861 | #endif |
864 | 862 | #endif |
865 | 863 | |
864 | +/* Device control registers */ | |
865 | +int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp); | |
866 | +int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val); | |
867 | + | |
866 | 868 | #define TARGET_PAGE_BITS 12 |
867 | 869 | #include "cpu-all.h" |
868 | 870 | ... | ... |
target-ppc/op_helper.c
... | ... | @@ -1249,20 +1249,26 @@ void do_load_dcr (void) |
1249 | 1249 | { |
1250 | 1250 | target_ulong val; |
1251 | 1251 | |
1252 | - if (unlikely(env->dcr_read == NULL)) | |
1252 | + if (unlikely(env->dcr_env == NULL)) { | |
1253 | + printf("No DCR environment\n"); | |
1253 | 1254 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL); |
1254 | - else if (unlikely((*env->dcr_read)(env->dcr_env, T0, &val) != 0)) | |
1255 | + } else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) { | |
1256 | + printf("DCR read error\n"); | |
1255 | 1257 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG); |
1256 | - else | |
1258 | + } else { | |
1257 | 1259 | T0 = val; |
1260 | + } | |
1258 | 1261 | } |
1259 | 1262 | |
1260 | 1263 | void do_store_dcr (void) |
1261 | 1264 | { |
1262 | - if (unlikely(env->dcr_write == NULL)) | |
1265 | + if (unlikely(env->dcr_env == NULL)) { | |
1266 | + printf("No DCR environment\n"); | |
1263 | 1267 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL); |
1264 | - else if (unlikely((*env->dcr_write)(env->dcr_env, T0, T1) != 0)) | |
1268 | + } else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) { | |
1269 | + printf("DCR write error\n"); | |
1265 | 1270 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG); |
1271 | + } | |
1266 | 1272 | } |
1267 | 1273 | |
1268 | 1274 | void do_load_403_pb (int num) | ... | ... |
vl.h
... | ... | @@ -1147,6 +1147,13 @@ extern QEMUMachine shix_machine; |
1147 | 1147 | #ifdef TARGET_PPC |
1148 | 1148 | /* PowerPC hardware exceptions management helpers */ |
1149 | 1149 | ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq); |
1150 | +/* Embedded PowerPC DCR management */ | |
1151 | +typedef target_ulong (*dcr_read_cb)(void *opaque, int dcrn); | |
1152 | +typedef void (*dcr_write_cb)(void *opaque, int dcrn, target_ulong val); | |
1153 | +int ppc_dcr_init (CPUState *env, int (*dcr_read_error)(int dcrn), | |
1154 | + int (*dcr_write_error)(int dcrn)); | |
1155 | +int ppc_dcr_register (CPUState *env, int dcrn, void *opaque, | |
1156 | + dcr_read_cb drc_read, dcr_write_cb dcr_write); | |
1150 | 1157 | #endif |
1151 | 1158 | void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); |
1152 | 1159 | ... | ... |