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