Revision a062e36c hw/ppc.c
b/hw/ppc.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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) |
Also available in: Unified diff