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