Commit a062e36c58738321295e1031bebb1b89a0cdf01a
1 parent
4887d78b
Implement the PowerPC alternate time-base, following the 2.04 specification.
Share most code with the time-base management routines. Remove time-base write routines from user-mode emulation environments. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3277 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
134 additions
and
57 deletions
darwin-user/main.c
| ... | ... | @@ -124,24 +124,14 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) |
| 124 | 124 | return cpu_ppc_get_tb(env) >> 32; |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | -static void cpu_ppc_store_tb (CPUState *env, uint64_t value) | |
| 127 | +uint32_t cpu_ppc_load_atbl (CPUState *env) | |
| 128 | 128 | { |
| 129 | - /* TO FIX */ | |
| 130 | -} | |
| 131 | - | |
| 132 | -void cpu_ppc_store_tbu (CPUState *env, uint32_t value) | |
| 133 | -{ | |
| 134 | - cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env)); | |
| 135 | -} | |
| 136 | - | |
| 137 | -void cpu_ppc_store_tbl (CPUState *env, uint32_t value) | |
| 138 | -{ | |
| 139 | - cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value); | |
| 129 | + return cpu_ppc_get_tb(env) & 0xFFFFFFFF; | |
| 140 | 130 | } |
| 141 | 131 | |
| 142 | -void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value) | |
| 132 | +uint32_t cpu_ppc_load_atbu (CPUState *env) | |
| 143 | 133 | { |
| 144 | - cpu_ppc_store_tbu( env, value ); | |
| 134 | + return cpu_ppc_get_tb(env) >> 32; | |
| 145 | 135 | } |
| 146 | 136 | |
| 147 | 137 | uint32_t cpu_ppc601_load_rtcu (CPUState *env) | ... | ... |
hw/ppc.c
| ... | ... | @@ -408,6 +408,7 @@ void ppc405_irq_init (CPUState *env) |
| 408 | 408 | struct ppc_tb_t { |
| 409 | 409 | /* Time base management */ |
| 410 | 410 | int64_t tb_offset; /* Compensation */ |
| 411 | + int64_t atb_offset; /* Compensation */ | |
| 411 | 412 | uint32_t tb_freq; /* TB frequency */ |
| 412 | 413 | /* Decrementer management */ |
| 413 | 414 | uint64_t decr_next; /* Tick for next decr interrupt */ |
| ... | ... | @@ -422,7 +423,7 @@ struct ppc_tb_t { |
| 422 | 423 | void *opaque; |
| 423 | 424 | }; |
| 424 | 425 | |
| 425 | -static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env) | |
| 426 | +static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, int64_t tb_offset) | |
| 426 | 427 | { |
| 427 | 428 | /* TB time in tb periods */ |
| 428 | 429 | return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset, |
| ... | ... | @@ -434,19 +435,10 @@ uint32_t cpu_ppc_load_tbl (CPUState *env) |
| 434 | 435 | ppc_tb_t *tb_env = env->tb_env; |
| 435 | 436 | uint64_t tb; |
| 436 | 437 | |
| 437 | - tb = cpu_ppc_get_tb(tb_env); | |
| 438 | -#ifdef PPC_DEBUG_TB | |
| 439 | - { | |
| 440 | - static int last_time; | |
| 441 | - int now; | |
| 442 | - now = time(NULL); | |
| 443 | - if (last_time != now) { | |
| 444 | - last_time = now; | |
| 445 | - if (loglevel != 0) { | |
| 446 | - fprintf(logfile, "%s: tb=0x%016lx %d %08lx\n", | |
| 447 | - __func__, tb, now, tb_env->tb_offset); | |
| 448 | - } | |
| 449 | - } | |
| 438 | + tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); | |
| 439 | +#if defined(PPC_DEBUG_TB) | |
| 440 | + if (loglevel != 0) { | |
| 441 | + fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); | |
| 450 | 442 | } |
| 451 | 443 | #endif |
| 452 | 444 | |
| ... | ... | @@ -458,7 +450,7 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) |
| 458 | 450 | ppc_tb_t *tb_env = env->tb_env; |
| 459 | 451 | uint64_t tb; |
| 460 | 452 | |
| 461 | - tb = cpu_ppc_get_tb(tb_env); | |
| 453 | + tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); | |
| 462 | 454 | #if defined(PPC_DEBUG_TB) |
| 463 | 455 | if (loglevel != 0) { |
| 464 | 456 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); |
| ... | ... | @@ -468,32 +460,89 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) |
| 468 | 460 | return tb >> 32; |
| 469 | 461 | } |
| 470 | 462 | |
| 471 | -static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value) | |
| 463 | +static inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, int64_t *tb_offsetp, | |
| 464 | + uint64_t value) | |
| 472 | 465 | { |
| 473 | - tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq) | |
| 466 | + *tb_offsetp = muldiv64(value, ticks_per_sec, tb_env->tb_freq) | |
| 474 | 467 | - qemu_get_clock(vm_clock); |
| 475 | 468 | #ifdef PPC_DEBUG_TB |
| 476 | 469 | if (loglevel != 0) { |
| 477 | 470 | fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value, |
| 478 | - tb_env->tb_offset); | |
| 471 | + *tb_offsetp); | |
| 479 | 472 | } |
| 480 | 473 | #endif |
| 481 | 474 | } |
| 482 | 475 | |
| 476 | +void cpu_ppc_store_tbl (CPUState *env, uint32_t value) | |
| 477 | +{ | |
| 478 | + ppc_tb_t *tb_env = env->tb_env; | |
| 479 | + uint64_t tb; | |
| 480 | + | |
| 481 | + tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); | |
| 482 | + tb &= 0xFFFFFFFF00000000ULL; | |
| 483 | + cpu_ppc_store_tb(tb_env, &tb_env->tb_offset, tb | (uint64_t)value); | |
| 484 | +} | |
| 485 | + | |
| 483 | 486 | void cpu_ppc_store_tbu (CPUState *env, uint32_t value) |
| 484 | 487 | { |
| 485 | 488 | ppc_tb_t *tb_env = env->tb_env; |
| 489 | + uint64_t tb; | |
| 486 | 490 | |
| 487 | - cpu_ppc_store_tb(tb_env, | |
| 488 | - ((uint64_t)value << 32) | cpu_ppc_load_tbl(env)); | |
| 491 | + tb = cpu_ppc_get_tb(tb_env, tb_env->tb_offset); | |
| 492 | + tb &= 0x00000000FFFFFFFFULL; | |
| 493 | + cpu_ppc_store_tb(tb_env, &tb_env->tb_offset, | |
| 494 | + ((uint64_t)value << 32) | tb); | |
| 489 | 495 | } |
| 490 | 496 | |
| 491 | -void cpu_ppc_store_tbl (CPUState *env, uint32_t value) | |
| 497 | +uint32_t cpu_ppc_load_atbl (CPUState *env) | |
| 498 | +{ | |
| 499 | + ppc_tb_t *tb_env = env->tb_env; | |
| 500 | + uint64_t tb; | |
| 501 | + | |
| 502 | + tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); | |
| 503 | +#if defined(PPC_DEBUG_TB) | |
| 504 | + if (loglevel != 0) { | |
| 505 | + fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); | |
| 506 | + } | |
| 507 | +#endif | |
| 508 | + | |
| 509 | + return tb & 0xFFFFFFFF; | |
| 510 | +} | |
| 511 | + | |
| 512 | +uint32_t cpu_ppc_load_atbu (CPUState *env) | |
| 513 | +{ | |
| 514 | + ppc_tb_t *tb_env = env->tb_env; | |
| 515 | + uint64_t tb; | |
| 516 | + | |
| 517 | + tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); | |
| 518 | +#if defined(PPC_DEBUG_TB) | |
| 519 | + if (loglevel != 0) { | |
| 520 | + fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); | |
| 521 | + } | |
| 522 | +#endif | |
| 523 | + | |
| 524 | + return tb >> 32; | |
| 525 | +} | |
| 526 | + | |
| 527 | +void cpu_ppc_store_atbl (CPUState *env, uint32_t value) | |
| 528 | +{ | |
| 529 | + ppc_tb_t *tb_env = env->tb_env; | |
| 530 | + uint64_t tb; | |
| 531 | + | |
| 532 | + tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); | |
| 533 | + tb &= 0xFFFFFFFF00000000ULL; | |
| 534 | + cpu_ppc_store_tb(tb_env, &tb_env->atb_offset, tb | (uint64_t)value); | |
| 535 | +} | |
| 536 | + | |
| 537 | +void cpu_ppc_store_atbu (CPUState *env, uint32_t value) | |
| 492 | 538 | { |
| 493 | 539 | ppc_tb_t *tb_env = env->tb_env; |
| 540 | + uint64_t tb; | |
| 494 | 541 | |
| 495 | - cpu_ppc_store_tb(tb_env, | |
| 496 | - ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value); | |
| 542 | + tb = cpu_ppc_get_tb(tb_env, tb_env->atb_offset); | |
| 543 | + tb &= 0x00000000FFFFFFFFULL; | |
| 544 | + cpu_ppc_store_tb(tb_env, &tb_env->atb_offset, | |
| 545 | + ((uint64_t)value << 32) | tb); | |
| 497 | 546 | } |
| 498 | 547 | |
| 499 | 548 | static inline uint32_t _cpu_ppc_load_decr (CPUState *env, uint64_t *next) | ... | ... |
linux-user/main.c
| ... | ... | @@ -664,7 +664,6 @@ void cpu_loop (CPUSPARCState *env) |
| 664 | 664 | #endif |
| 665 | 665 | |
| 666 | 666 | #ifdef TARGET_PPC |
| 667 | - | |
| 668 | 667 | static inline uint64_t cpu_ppc_get_tb (CPUState *env) |
| 669 | 668 | { |
| 670 | 669 | /* TO FIX */ |
| ... | ... | @@ -681,32 +680,19 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) |
| 681 | 680 | return cpu_ppc_get_tb(env) >> 32; |
| 682 | 681 | } |
| 683 | 682 | |
| 684 | -static void cpu_ppc_store_tb (CPUState *env, uint64_t value) | |
| 685 | -{ | |
| 686 | - /* TO FIX */ | |
| 687 | -} | |
| 688 | - | |
| 689 | -void cpu_ppc_store_tbu (CPUState *env, uint32_t value) | |
| 683 | +uint32_t cpu_ppc_load_atbl (CPUState *env) | |
| 690 | 684 | { |
| 691 | - cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env)); | |
| 685 | + return cpu_ppc_get_tb(env) & 0xFFFFFFFF; | |
| 692 | 686 | } |
| 693 | 687 | |
| 694 | -void cpu_ppc_store_tbl (CPUState *env, uint32_t value) | |
| 688 | +uint32_t cpu_ppc_load_atbu (CPUState *env) | |
| 695 | 689 | { |
| 696 | - cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value); | |
| 690 | + return cpu_ppc_get_tb(env) >> 32; | |
| 697 | 691 | } |
| 698 | 692 | |
| 699 | -void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value) | |
| 700 | -__attribute__ (( alias ("cpu_ppc_store_tbu") )); | |
| 701 | - | |
| 702 | 693 | uint32_t cpu_ppc601_load_rtcu (CPUState *env) |
| 703 | 694 | __attribute__ (( alias ("cpu_ppc_load_tbu") )); |
| 704 | 695 | |
| 705 | -void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value) | |
| 706 | -{ | |
| 707 | - cpu_ppc_store_tbl(env, value & 0x3FFFFF80); | |
| 708 | -} | |
| 709 | - | |
| 710 | 696 | uint32_t cpu_ppc601_load_rtcl (CPUState *env) |
| 711 | 697 | { |
| 712 | 698 | return cpu_ppc_load_tbl(env) & 0x3FFFFF80; | ... | ... |
target-ppc/cpu.h
| ... | ... | @@ -625,6 +625,10 @@ uint32_t cpu_ppc_load_tbl (CPUPPCState *env); |
| 625 | 625 | uint32_t cpu_ppc_load_tbu (CPUPPCState *env); |
| 626 | 626 | void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value); |
| 627 | 627 | void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value); |
| 628 | +uint32_t cpu_ppc_load_atbl (CPUPPCState *env); | |
| 629 | +uint32_t cpu_ppc_load_atbu (CPUPPCState *env); | |
| 630 | +void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value); | |
| 631 | +void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value); | |
| 628 | 632 | uint32_t cpu_ppc_load_decr (CPUPPCState *env); |
| 629 | 633 | void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value); |
| 630 | 634 | #if defined(TARGET_PPC64H) |
| ... | ... | @@ -798,8 +802,8 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val); |
| 798 | 802 | #define SPR_BOOKE_SPEFSCR (0x200) |
| 799 | 803 | #define SPR_E500_BBEAR (0x201) |
| 800 | 804 | #define SPR_E500_BBTAR (0x202) |
| 801 | -#define SPR_BOOKE_ATBL (0x20E) | |
| 802 | -#define SPR_BOOKE_ATBU (0x20F) | |
| 805 | +#define SPR_ATBL (0x20E) | |
| 806 | +#define SPR_ATBU (0x20F) | |
| 803 | 807 | #define SPR_IBAT0U (0x210) |
| 804 | 808 | #define SPR_BOOKE_IVOR32 (0x210) |
| 805 | 809 | #define SPR_IBAT0L (0x211) | ... | ... |
target-ppc/op.c
| ... | ... | @@ -423,6 +423,18 @@ void OPPROTO op_load_tbu (void) |
| 423 | 423 | RETURN(); |
| 424 | 424 | } |
| 425 | 425 | |
| 426 | +void OPPROTO op_load_atbl (void) | |
| 427 | +{ | |
| 428 | + T0 = cpu_ppc_load_atbl(env); | |
| 429 | + RETURN(); | |
| 430 | +} | |
| 431 | + | |
| 432 | +void OPPROTO op_load_atbu (void) | |
| 433 | +{ | |
| 434 | + T0 = cpu_ppc_load_atbu(env); | |
| 435 | + RETURN(); | |
| 436 | +} | |
| 437 | + | |
| 426 | 438 | #if !defined(CONFIG_USER_ONLY) |
| 427 | 439 | void OPPROTO op_store_tbl (void) |
| 428 | 440 | { |
| ... | ... | @@ -436,6 +448,18 @@ void OPPROTO op_store_tbu (void) |
| 436 | 448 | RETURN(); |
| 437 | 449 | } |
| 438 | 450 | |
| 451 | +void OPPROTO op_store_atbl (void) | |
| 452 | +{ | |
| 453 | + cpu_ppc_store_atbl(env, T0); | |
| 454 | + RETURN(); | |
| 455 | +} | |
| 456 | + | |
| 457 | +void OPPROTO op_store_atbu (void) | |
| 458 | +{ | |
| 459 | + cpu_ppc_store_atbu(env, T0); | |
| 460 | + RETURN(); | |
| 461 | +} | |
| 462 | + | |
| 439 | 463 | void OPPROTO op_load_decr (void) |
| 440 | 464 | { |
| 441 | 465 | T0 = cpu_ppc_load_decr(env); | ... | ... |
target-ppc/translate_init.c
| ... | ... | @@ -162,6 +162,18 @@ static void spr_read_tbu (void *opaque, int sprn) |
| 162 | 162 | gen_op_load_tbu(); |
| 163 | 163 | } |
| 164 | 164 | |
| 165 | +__attribute__ (( unused )) | |
| 166 | +static void spr_read_atbl (void *opaque, int sprn) | |
| 167 | +{ | |
| 168 | + gen_op_load_atbl(); | |
| 169 | +} | |
| 170 | + | |
| 171 | +__attribute__ (( unused )) | |
| 172 | +static void spr_read_atbu (void *opaque, int sprn) | |
| 173 | +{ | |
| 174 | + gen_op_load_atbu(); | |
| 175 | +} | |
| 176 | + | |
| 165 | 177 | #if !defined(CONFIG_USER_ONLY) |
| 166 | 178 | static void spr_write_tbl (void *opaque, int sprn) |
| 167 | 179 | { |
| ... | ... | @@ -172,6 +184,18 @@ static void spr_write_tbu (void *opaque, int sprn) |
| 172 | 184 | { |
| 173 | 185 | gen_op_store_tbu(); |
| 174 | 186 | } |
| 187 | + | |
| 188 | +__attribute__ (( unused )) | |
| 189 | +static void spr_write_atbl (void *opaque, int sprn) | |
| 190 | +{ | |
| 191 | + gen_op_store_atbl(); | |
| 192 | +} | |
| 193 | + | |
| 194 | +__attribute__ (( unused )) | |
| 195 | +static void spr_write_atbu (void *opaque, int sprn) | |
| 196 | +{ | |
| 197 | + gen_op_store_atbu(); | |
| 198 | +} | |
| 175 | 199 | #endif |
| 176 | 200 | |
| 177 | 201 | #if !defined(CONFIG_USER_ONLY) | ... | ... |