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,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 | #if 0 | 645 | #if 0 |
| 551 | /*****************************************************************************/ | 646 | /*****************************************************************************/ |
| 552 | /* Handle system reset (for now, just stop emulation) */ | 647 | /* Handle system reset (for now, just stop emulation) */ |
target-ppc/cpu.h
| @@ -730,8 +730,6 @@ struct CPUPPCState { | @@ -730,8 +730,6 @@ struct CPUPPCState { | ||
| 730 | /* Time base and decrementer */ | 730 | /* Time base and decrementer */ |
| 731 | ppc_tb_t *tb_env; | 731 | ppc_tb_t *tb_env; |
| 732 | /* Device control registers */ | 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 | ppc_dcr_t *dcr_env; | 733 | ppc_dcr_t *dcr_env; |
| 736 | 734 | ||
| 737 | /* PowerPC TLB registers (for 4xx and 60x software driven TLBs) */ | 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,6 +861,10 @@ void store_booke_tsr (CPUPPCState *env, target_ulong val); | ||
| 863 | #endif | 861 | #endif |
| 864 | #endif | 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 | #define TARGET_PAGE_BITS 12 | 868 | #define TARGET_PAGE_BITS 12 |
| 867 | #include "cpu-all.h" | 869 | #include "cpu-all.h" |
| 868 | 870 |
target-ppc/op_helper.c
| @@ -1249,20 +1249,26 @@ void do_load_dcr (void) | @@ -1249,20 +1249,26 @@ void do_load_dcr (void) | ||
| 1249 | { | 1249 | { |
| 1250 | target_ulong val; | 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 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL); | 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 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG); | 1257 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG); |
| 1256 | - else | 1258 | + } else { |
| 1257 | T0 = val; | 1259 | T0 = val; |
| 1260 | + } | ||
| 1258 | } | 1261 | } |
| 1259 | 1262 | ||
| 1260 | void do_store_dcr (void) | 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 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_INVAL); | 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 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG); | 1270 | do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_PRIV_REG); |
| 1271 | + } | ||
| 1266 | } | 1272 | } |
| 1267 | 1273 | ||
| 1268 | void do_load_403_pb (int num) | 1274 | void do_load_403_pb (int num) |
vl.h
| @@ -1147,6 +1147,13 @@ extern QEMUMachine shix_machine; | @@ -1147,6 +1147,13 @@ extern QEMUMachine shix_machine; | ||
| 1147 | #ifdef TARGET_PPC | 1147 | #ifdef TARGET_PPC |
| 1148 | /* PowerPC hardware exceptions management helpers */ | 1148 | /* PowerPC hardware exceptions management helpers */ |
| 1149 | ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq); | 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 | #endif | 1157 | #endif |
| 1151 | void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); | 1158 | void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); |
| 1152 | 1159 |