Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions qemu/hw/ppc/ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
# define LOG_TB(...) do { } while (0)
#endif

#if 0
#if 1
static void cpu_ppc_tb_stop (CPUPPCState *env);
static void cpu_ppc_tb_start (CPUPPCState *env);
#endif
Expand Down Expand Up @@ -90,7 +90,9 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
env->pending_interrupts, CPU(cpu)->interrupt_request);
}

#if 0
#if 1
// Broadway clock speed
#define TB_TIMER_CLOCK (243000000u/4000)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it from original qemu code?

Copy link
Author

@Fancy2209 Fancy2209 Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, for my specific case I needed to use the Wii CPU's Timebase Frequency which is what this value represents
I can replace it with a value used by Qemu somewhere if desired, not sure which one since timebase frequency is different per machine in qemu due to it being hardware and software implementation dependent

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops sorry I thought it was from QEMU. How does QEMU ever set that?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qemu hardcodes the frequency per machine
E.g. old world PowerMac frequency is set here
https://github.com/qemu/qemu/blob/593aee5df98b4a862ff8841a57ea3dbf22131a5f/hw/ppc/mac_oldworld.c#L117

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh in that case, we have cpu_model to do this things (see uc_ctl_set_cpu_model). Does the Wii use a specific cpu model?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh in that case, we have cpu_model to do this things (see uc_ctl_set_cpu_model). Does the Wii use a specific cpu model?

On the code I've just been using PPC 750 who is the closest qemu has
I'll look into that, thanks!

/* PowerPC 6xx / 7xx internal IRQ controller */
static void ppc6xx_set_irq(void *opaque, int pin, int level)
{
Expand All @@ -111,6 +113,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
LOG_IRQ("%s: %s the time base\n",
__func__, level ? "start" : "stop");
if (level) {
cpu_ppc_tb_init(env, TB_TIMER_CLOCK);
cpu_ppc_tb_start(env);
} else {
cpu_ppc_tb_stop(env);
Expand Down Expand Up @@ -174,6 +177,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)

void ppc6xx_irq_init(PowerPCCPU *cpu)
{
ppc6xx_set_irq((void*)cpu, PPC6xx_INPUT_TBEN, 1);
#if 0
CPUPPCState *env = &cpu->env;

Expand Down Expand Up @@ -735,7 +739,7 @@ void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value)
&tb_env->tb_offset, tb);
}

#if 0
#if 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can safely remote all such #if 0 swtiches instead of changing it to #if 1.

static void cpu_ppc_tb_stop (CPUPPCState *env)
{
ppc_tb_t *tb_env = env->tb_env;
Expand Down Expand Up @@ -1565,5 +1569,6 @@ void ppc_irq_reset(PowerPCCPU *cpu)
CPUPPCState *env = &cpu->env;

env->irq_input_state = 0;
ppc6xx_set_irq((void*)cpu, PPC6xx_INPUT_TBEN, 0);
// kvmppc_set_interrupt(cpu, PPC_INTERRUPT_EXT, 0);
}
12 changes: 6 additions & 6 deletions qemu/target/ppc/translate_init.inc.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ static void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)

/* SPR common to all non-embedded PowerPC */
/* DECR */
#if 0
#if 1
static void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
Expand All @@ -187,7 +187,7 @@ static void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
#define spr_read_decr spr_read_generic
#endif

#if 0
#if 1
static void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
Expand All @@ -205,7 +205,7 @@ static void spr_write_decr(DisasContext *ctx, int sprn, int gprn)

/* SPR common to all non-embedded PowerPC, except 601 */
/* Time base */
#if 0
#if 1
static void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
Expand All @@ -222,7 +222,7 @@ static void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
#define spr_read_tbl spr_read_generic
#endif

#if 0
#if 1
static void spr_read_tbu(DisasContext *ctx, int gprn, int sprn)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
Expand Down Expand Up @@ -255,7 +255,7 @@ static void spr_read_atbu(DisasContext *ctx, int gprn, int sprn)
}
#endif

#if 0
#if 1
static void spr_write_tbl(DisasContext *ctx, int sprn, int gprn)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
Expand All @@ -273,7 +273,7 @@ static void spr_write_tbl(DisasContext *ctx, int sprn, int gprn)
#endif


#if 0
#if 1
static void spr_write_tbu(DisasContext *ctx, int sprn, int gprn)
{
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
Expand Down
33 changes: 26 additions & 7 deletions tests/unit/test_ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,34 @@ static void test_ppc32_cr(void)

static void test_ppc32_spr_time(void)
{
char code[] = ("\x7c\x76\x02\xa6" // mfspr r3, DEC
"\x7c\x6d\x42\xa6" // mfspr r3, TBUr
);

uint32_t r3_val;
uc_engine *uc;
uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code,
sizeof(code) - 1);

OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
char code_dec[] = "\x7c\x76\x02\xa6"; // mfspr r3, DEC
uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code_dec,
sizeof(code_dec) - 1);

OK(uc_emu_start(uc, code_start, code_start + sizeof(code_dec) - 1, 0, 0));
OK(uc_reg_read(uc, UC_PPC_REG_3, &r3_val));
printf("DEC: 0x%08x\n", BEINT32(r3_val));
OK(uc_close(uc));

char code_tbur[] = "\x7c\x6d\x42\xa6"; // mfspr r3, TBUr
uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code_tbur,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider splitting these into 2 or 3 tests.

sizeof(code_tbur) - 1);

OK(uc_emu_start(uc, code_start, code_start + sizeof(code_tbur) - 1, 0, 0));
OK(uc_reg_read(uc, UC_PPC_REG_3, &r3_val));
printf("TBUr: 0x%08x\n", BEINT32(r3_val));
OK(uc_close(uc));

char code_tblr[] = "\x7c\x6c\x42\xa6"; // mfspr r3, TBLr
uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code_tblr,
sizeof(code_tblr) - 1);

OK(uc_emu_start(uc, code_start, code_start + sizeof(code_tblr) - 1, 0, 0));
OK(uc_reg_read(uc, UC_PPC_REG_3, &r3_val));
printf("TBLr: 0x%08x\n", BEINT32(r3_val));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a simple TEST_CHECK ?

OK(uc_close(uc));
}

Expand Down
Loading