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 | ... | ... |