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,24 +124,14 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | ||
| 124 | return cpu_ppc_get_tb(env) >> 32; | 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 | uint32_t cpu_ppc601_load_rtcu (CPUState *env) | 137 | uint32_t cpu_ppc601_load_rtcu (CPUState *env) |
hw/ppc.c
| @@ -408,6 +408,7 @@ void ppc405_irq_init (CPUState *env) | @@ -408,6 +408,7 @@ void ppc405_irq_init (CPUState *env) | ||
| 408 | struct ppc_tb_t { | 408 | struct ppc_tb_t { |
| 409 | /* Time base management */ | 409 | /* Time base management */ |
| 410 | int64_t tb_offset; /* Compensation */ | 410 | int64_t tb_offset; /* Compensation */ |
| 411 | + int64_t atb_offset; /* Compensation */ | ||
| 411 | uint32_t tb_freq; /* TB frequency */ | 412 | uint32_t tb_freq; /* TB frequency */ |
| 412 | /* Decrementer management */ | 413 | /* Decrementer management */ |
| 413 | uint64_t decr_next; /* Tick for next decr interrupt */ | 414 | uint64_t decr_next; /* Tick for next decr interrupt */ |
| @@ -422,7 +423,7 @@ struct ppc_tb_t { | @@ -422,7 +423,7 @@ struct ppc_tb_t { | ||
| 422 | void *opaque; | 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 | /* TB time in tb periods */ | 428 | /* TB time in tb periods */ |
| 428 | return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset, | 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,19 +435,10 @@ uint32_t cpu_ppc_load_tbl (CPUState *env) | ||
| 434 | ppc_tb_t *tb_env = env->tb_env; | 435 | ppc_tb_t *tb_env = env->tb_env; |
| 435 | uint64_t tb; | 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 | #endif | 443 | #endif |
| 452 | 444 | ||
| @@ -458,7 +450,7 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | @@ -458,7 +450,7 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | ||
| 458 | ppc_tb_t *tb_env = env->tb_env; | 450 | ppc_tb_t *tb_env = env->tb_env; |
| 459 | uint64_t tb; | 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 | #if defined(PPC_DEBUG_TB) | 454 | #if defined(PPC_DEBUG_TB) |
| 463 | if (loglevel != 0) { | 455 | if (loglevel != 0) { |
| 464 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); | 456 | fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb); |
| @@ -468,32 +460,89 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | @@ -468,32 +460,89 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | ||
| 468 | return tb >> 32; | 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 | - qemu_get_clock(vm_clock); | 467 | - qemu_get_clock(vm_clock); |
| 475 | #ifdef PPC_DEBUG_TB | 468 | #ifdef PPC_DEBUG_TB |
| 476 | if (loglevel != 0) { | 469 | if (loglevel != 0) { |
| 477 | fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value, | 470 | fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value, |
| 478 | - tb_env->tb_offset); | 471 | + *tb_offsetp); |
| 479 | } | 472 | } |
| 480 | #endif | 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 | void cpu_ppc_store_tbu (CPUState *env, uint32_t value) | 486 | void cpu_ppc_store_tbu (CPUState *env, uint32_t value) |
| 484 | { | 487 | { |
| 485 | ppc_tb_t *tb_env = env->tb_env; | 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 | ppc_tb_t *tb_env = env->tb_env; | 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 | static inline uint32_t _cpu_ppc_load_decr (CPUState *env, uint64_t *next) | 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,7 +664,6 @@ void cpu_loop (CPUSPARCState *env) | ||
| 664 | #endif | 664 | #endif |
| 665 | 665 | ||
| 666 | #ifdef TARGET_PPC | 666 | #ifdef TARGET_PPC |
| 667 | - | ||
| 668 | static inline uint64_t cpu_ppc_get_tb (CPUState *env) | 667 | static inline uint64_t cpu_ppc_get_tb (CPUState *env) |
| 669 | { | 668 | { |
| 670 | /* TO FIX */ | 669 | /* TO FIX */ |
| @@ -681,32 +680,19 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | @@ -681,32 +680,19 @@ uint32_t cpu_ppc_load_tbu (CPUState *env) | ||
| 681 | return cpu_ppc_get_tb(env) >> 32; | 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 | uint32_t cpu_ppc601_load_rtcu (CPUState *env) | 693 | uint32_t cpu_ppc601_load_rtcu (CPUState *env) |
| 703 | __attribute__ (( alias ("cpu_ppc_load_tbu") )); | 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 | uint32_t cpu_ppc601_load_rtcl (CPUState *env) | 696 | uint32_t cpu_ppc601_load_rtcl (CPUState *env) |
| 711 | { | 697 | { |
| 712 | return cpu_ppc_load_tbl(env) & 0x3FFFFF80; | 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,6 +625,10 @@ uint32_t cpu_ppc_load_tbl (CPUPPCState *env); | ||
| 625 | uint32_t cpu_ppc_load_tbu (CPUPPCState *env); | 625 | uint32_t cpu_ppc_load_tbu (CPUPPCState *env); |
| 626 | void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value); | 626 | void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value); |
| 627 | void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value); | 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 | uint32_t cpu_ppc_load_decr (CPUPPCState *env); | 632 | uint32_t cpu_ppc_load_decr (CPUPPCState *env); |
| 629 | void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value); | 633 | void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value); |
| 630 | #if defined(TARGET_PPC64H) | 634 | #if defined(TARGET_PPC64H) |
| @@ -798,8 +802,8 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val); | @@ -798,8 +802,8 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val); | ||
| 798 | #define SPR_BOOKE_SPEFSCR (0x200) | 802 | #define SPR_BOOKE_SPEFSCR (0x200) |
| 799 | #define SPR_E500_BBEAR (0x201) | 803 | #define SPR_E500_BBEAR (0x201) |
| 800 | #define SPR_E500_BBTAR (0x202) | 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 | #define SPR_IBAT0U (0x210) | 807 | #define SPR_IBAT0U (0x210) |
| 804 | #define SPR_BOOKE_IVOR32 (0x210) | 808 | #define SPR_BOOKE_IVOR32 (0x210) |
| 805 | #define SPR_IBAT0L (0x211) | 809 | #define SPR_IBAT0L (0x211) |
target-ppc/op.c
| @@ -423,6 +423,18 @@ void OPPROTO op_load_tbu (void) | @@ -423,6 +423,18 @@ void OPPROTO op_load_tbu (void) | ||
| 423 | RETURN(); | 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 | #if !defined(CONFIG_USER_ONLY) | 438 | #if !defined(CONFIG_USER_ONLY) |
| 427 | void OPPROTO op_store_tbl (void) | 439 | void OPPROTO op_store_tbl (void) |
| 428 | { | 440 | { |
| @@ -436,6 +448,18 @@ void OPPROTO op_store_tbu (void) | @@ -436,6 +448,18 @@ void OPPROTO op_store_tbu (void) | ||
| 436 | RETURN(); | 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 | void OPPROTO op_load_decr (void) | 463 | void OPPROTO op_load_decr (void) |
| 440 | { | 464 | { |
| 441 | T0 = cpu_ppc_load_decr(env); | 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,6 +162,18 @@ static void spr_read_tbu (void *opaque, int sprn) | ||
| 162 | gen_op_load_tbu(); | 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 | #if !defined(CONFIG_USER_ONLY) | 177 | #if !defined(CONFIG_USER_ONLY) |
| 166 | static void spr_write_tbl (void *opaque, int sprn) | 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,6 +184,18 @@ static void spr_write_tbu (void *opaque, int sprn) | ||
| 172 | { | 184 | { |
| 173 | gen_op_store_tbu(); | 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 | #endif | 199 | #endif |
| 176 | 200 | ||
| 177 | #if !defined(CONFIG_USER_ONLY) | 201 | #if !defined(CONFIG_USER_ONLY) |