Skip to content

Commit

Permalink
Remove ppc_cur_instruction global variable
Browse files Browse the repository at this point in the history
Replace it wth an explicit opcode parameter that is passed around. That
is both slightly easier to reason about (to trace where it comes from)
and slightly faster, since it can be read from a register.

On my machine takes booting to "Welcome to Macintosh" being output in
a verbose boot of Mac OS X 10.2.8 from 31.8s to 30.6s (average of 5
runs, measured using deterministic mode and looking at when execution
reaches PC 0x90004a88).
  • Loading branch information
mihaip committed Nov 28, 2024
1 parent 31bc6f7 commit 564c43c
Show file tree
Hide file tree
Showing 11 changed files with 1,093 additions and 1,090 deletions.
244 changes: 122 additions & 122 deletions cpu/ppc/poweropcodes.cpp

Large diffs are not rendered by default.

405 changes: 202 additions & 203 deletions cpu/ppc/ppcemu.h

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions cpu/ppc/ppcexceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,17 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
throw std::invalid_argument(exc_descriptor);
}

void ppc_floating_point_exception() {
void ppc_floating_point_exception(uint32_t opcode) {
LOG_F(ERROR, "Floating point exception at 0x%08x for instruction 0x%08x",
ppc_state.pc, ppc_cur_instruction);
ppc_state.pc, opcode);
// mmu_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::FPU_EXCEPTION);
}

void ppc_alignment_exception(uint32_t ea)
void ppc_alignment_exception(uint32_t opcode, uint32_t ea)
{
uint32_t dsisr;

switch (ppc_cur_instruction & 0xfc000000) {
switch (opcode & 0xfc000000) {
case 0x80000000: // lwz
case 0x90000000: // stw
case 0xa0000000: // lhz
Expand All @@ -228,11 +228,11 @@ void ppc_alignment_exception(uint32_t ea)
case 0xd4000000: // stfsu
case 0xdc000000: // stfdu
// indirect with immediate index
dsisr = ((ppc_cur_instruction >> 12) & 0x00004000) // bit 17 — Set to bit 5 of the instruction.
| ((ppc_cur_instruction >> 17) & 0x00003c00); // bits 18–21 - set to bits 1–4 of the instruction.
dsisr = ((opcode >> 12) & 0x00004000) // bit 17 — Set to bit 5 of the instruction.
| ((opcode >> 17) & 0x00003c00); // bits 18–21 - set to bits 1–4 of the instruction.
break;
case 0x7c000000:
switch (ppc_cur_instruction & 0xfc0007ff) {
switch (opcode & 0xfc0007ff) {
case 0x7c000028: // lwarx (invalid form - bits 15-21 of DSISR are identical to those of lwz)
case 0x7c0002aa: // lwax (64-bit only)
case 0x7c00042a: // lswx
Expand Down Expand Up @@ -266,12 +266,12 @@ void ppc_alignment_exception(uint32_t ea)
case 0x7c00056e: // stfsux
case 0x7c0005ee: // stfdux
indirect_with_index:
dsisr = ((ppc_cur_instruction << 14) & 0x00018000) // bits 15–16 - set to bits 29–30 of the instruction.
| ((ppc_cur_instruction << 8) & 0x00004000) // bit 17 - set to bit 25 of the instruction.
| ((ppc_cur_instruction << 3) & 0x00003c00); // bits 18–21 - set to bits 21–24 of the instruction.
dsisr = ((opcode << 14) & 0x00018000) // bits 15–16 - set to bits 29–30 of the instruction.
| ((opcode << 8) & 0x00004000) // bit 17 - set to bit 25 of the instruction.
| ((opcode << 3) & 0x00003c00); // bits 18–21 - set to bits 21–24 of the instruction.
break;
case 0x7c0007ec:
if ((ppc_cur_instruction & 0xffe007ff) == 0x7c0007ec) // dcbz
if ((opcode & 0xffe007ff) == 0x7c0007ec) // dcbz
goto indirect_with_index;
/* fallthrough */
default:
Expand All @@ -282,31 +282,31 @@ void ppc_alignment_exception(uint32_t ea)
unexpected_instruction:
dsisr = 0;
LOG_F(ERROR, "Alignment exception from unexpected instruction 0x%08x",
ppc_cur_instruction);
opcode);
}

// bits 22–26 - Set to bits 6–10 (source or destination) of the instruction.
// Undefined for dcbz.
dsisr |= ((ppc_cur_instruction >> 16) & 0x000003e0);
dsisr |= ((opcode >> 16) & 0x000003e0);

if ((ppc_cur_instruction & 0xfc000000) == 0xb8000000) { // lmw
if ((opcode & 0xfc000000) == 0xb8000000) { // lmw
LOG_F(ERROR, "Alignment exception from instruction 0x%08x (lmw). "
"What to set DSISR bits 27-31?", ppc_cur_instruction);
// dsisr |= ((ppc_cur_instruction >> ?) & 0x0000001f); // bits 27–31
"What to set DSISR bits 27-31?", opcode);
// dsisr |= ((opcode >> ?) & 0x0000001f); // bits 27–31
}
else if ((ppc_cur_instruction & 0xfc0007ff) == 0x7c0004aa) { // lswi
else if ((opcode & 0xfc0007ff) == 0x7c0004aa) { // lswi
LOG_F(ERROR, "Alignment exception from instruction 0x%08x (lswi). "
"What to set DSISR bits 27-31?", ppc_cur_instruction);
// dsisr |= ((ppc_cur_instruction >> ?) & 0x0000001f); // bits 27–31
"What to set DSISR bits 27-31?", opcode);
// dsisr |= ((opcode >> ?) & 0x0000001f); // bits 27–31
}
else if ((ppc_cur_instruction & 0xfc0007ff) == 0x7c00042a) { // lswx
else if ((opcode & 0xfc0007ff) == 0x7c00042a) { // lswx
LOG_F(ERROR, "Alignment exception from instruction 0x%08x (lswx). "
"What to set DSISR bits 27-31?", ppc_cur_instruction);
// dsisr |= ((ppc_cur_instruction >> ?) & 0x0000001f); // bits 27–31
"What to set DSISR bits 27-31?", opcode);
// dsisr |= ((opcode >> ?) & 0x0000001f); // bits 27–31
}
else {
// bits 27–31 - Set to bits 11–15 of the instruction (rA)
dsisr |= ((ppc_cur_instruction >> 16) & 0x0000001f);
dsisr |= ((opcode >> 16) & 0x0000001f);
}

ppc_state.spr[SPR::DSISR] = dsisr;
Expand Down
107 changes: 58 additions & 49 deletions cpu/ppc/ppcexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ Po_Cause power_off_reason = po_enter_debugger;

SetPRS ppc_state;

uint32_t ppc_cur_instruction; // Current instruction for the PPC
uint32_t ppc_next_instruction_address; // Used for branching, setting up the NIA

unsigned exec_flags; // execution control flags
Expand Down Expand Up @@ -208,7 +207,7 @@ static PPCOpcode SubOpcode63Grabber[2048];

/** Exception helpers. */

void ppc_illegalop() {
void ppc_illegalop(uint32_t opcode) {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
}

Expand All @@ -228,97 +227,97 @@ void ppc_release_int() {

/** Opcode decoding functions. */

static void ppc_opcode16() {
SubOpcode16Grabber[ppc_cur_instruction & 3]();
static void ppc_opcode16(uint32_t opcode) {
SubOpcode16Grabber[opcode & 3](opcode);
}

static void ppc_opcode18() {
SubOpcode18Grabber[ppc_cur_instruction & 3]();
static void ppc_opcode18(uint32_t opcode) {
SubOpcode18Grabber[opcode & 3](opcode);
}

template<field_601 for601>
static void ppc_opcode19() {
uint16_t subop_grab = ppc_cur_instruction & 0x7FF;
static void ppc_opcode19(uint32_t opcode) {
uint16_t subop_grab = opcode & 0x7FF;

switch (subop_grab) {
case 0:
ppc_mcrf();
ppc_mcrf(opcode);
break;
case 32:
ppc_bclr<LK0>();
ppc_bclr<LK0>(opcode);
break;
case 33:
ppc_bclr<LK1>();
ppc_bclr<LK1>(opcode);
break;
case 66:
ppc_crnor();
ppc_crnor(opcode);
break;
case 100:
ppc_rfi();
ppc_rfi(opcode);
break;
case 258:
ppc_crandc();
ppc_crandc(opcode);
break;
case 300:
ppc_isync();
ppc_isync(opcode);
break;
case 386:
ppc_crxor();
ppc_crxor(opcode);
break;
case 450:
ppc_crnand();
ppc_crnand(opcode);
break;
case 514:
ppc_crand();
ppc_crand(opcode);
break;
case 578:
ppc_creqv();
ppc_creqv(opcode);
break;
case 834:
ppc_crorc();
ppc_crorc(opcode);
break;
case 898:
ppc_cror();
ppc_cror(opcode);
break;
case 1056:
ppc_bcctr<LK0, for601>();
ppc_bcctr<LK0, for601>(opcode);
break;
case 1057:
ppc_bcctr<LK1, for601>();
ppc_bcctr<LK1, for601>(opcode);
break;
default:
ppc_illegalop();
ppc_illegalop(opcode);
}
}

template void ppc_opcode19<NOT601>();
template void ppc_opcode19<IS601>();
template void ppc_opcode19<NOT601>(uint32_t opcode);
template void ppc_opcode19<IS601>(uint32_t opcode);

static void ppc_opcode31() {
uint16_t subop_grab = ppc_cur_instruction & 0x7FFUL;
SubOpcode31Grabber[subop_grab]();
static void ppc_opcode31(uint32_t opcode) {
uint16_t subop_grab = opcode & 0x7FFUL;
SubOpcode31Grabber[subop_grab](opcode);
}

static void ppc_opcode59() {
uint16_t subop_grab = ppc_cur_instruction & 0x3FUL;
SubOpcode59Grabber[subop_grab]();
static void ppc_opcode59(uint32_t opcode) {
uint16_t subop_grab = opcode & 0x3FUL;
SubOpcode59Grabber[subop_grab](opcode);
}

static void ppc_opcode63() {
uint16_t subop_grab = ppc_cur_instruction & 0x7FFUL;
SubOpcode63Grabber[subop_grab]();
static void ppc_opcode63(uint32_t opcode) {
uint16_t subop_grab = opcode & 0x7FFUL;
SubOpcode63Grabber[subop_grab](opcode);
}

/* Dispatch using main opcode */
void ppc_main_opcode()
void ppc_main_opcode(uint32_t opcode)
{
#ifdef CPU_PROFILING
num_executed_instrs++;
#if defined(CPU_PROFILING_OPS)
num_opcodes[ppc_cur_instruction]++;
num_opcodes[opcode]++;
#endif
#endif
OpcodeGrabber[(ppc_cur_instruction >> 26) & 0x3F]();
OpcodeGrabber[(opcode >> 26) & 0x3F](opcode);
}

static long long cpu_now_ns() {
Expand Down Expand Up @@ -363,6 +362,7 @@ static void ppc_exec_inner()
{
uint64_t max_cycles;
uint32_t page_start, eb_start, eb_end;
uint32_t opcode;
uint8_t* pc_real;

max_cycles = 0;
Expand All @@ -376,10 +376,11 @@ static void ppc_exec_inner()
exec_flags = 0;

pc_real = mmu_translate_imem(eb_start);
opcode = ppc_read_instruction(pc_real);

// interpret execution block
while (power_on && ppc_state.pc < eb_end) {
ppc_main_opcode();
ppc_main_opcode(opcode);
if (g_icycles++ >= max_cycles || exec_timer) {
max_cycles = process_events();
}
Expand All @@ -389,18 +390,19 @@ static void ppc_exec_inner()
eb_start = ppc_next_instruction_address;
if (!(exec_flags & EXEF_RFI) && (eb_start & PPC_PAGE_MASK) == page_start) {
pc_real += (int)eb_start - (int)ppc_state.pc;
ppc_set_cur_instruction(pc_real);
opcode = ppc_read_instruction(pc_real);
} else {
page_start = eb_start & PPC_PAGE_MASK;
eb_end = page_start + PPC_PAGE_SIZE - 1;
pc_real = mmu_translate_imem(eb_start);
opcode = ppc_read_instruction(pc_real);
}
ppc_state.pc = eb_start;
exec_flags = 0;
} else {
ppc_state.pc += 4;
pc_real += 4;
ppc_set_cur_instruction(pc_real);
opcode = ppc_read_instruction(pc_real);
}
}
}
Expand Down Expand Up @@ -431,8 +433,9 @@ void ppc_exec_single()
return;
}

mmu_translate_imem(ppc_state.pc);
ppc_main_opcode();
uint8_t* pc_real = mmu_translate_imem(ppc_state.pc);
uint32_t opcode = ppc_read_instruction(pc_real);
ppc_main_opcode(opcode);
g_icycles++;
process_events();

Expand All @@ -452,6 +455,7 @@ static void ppc_exec_until_inner(const uint32_t goal_addr)
uint64_t max_cycles;
uint32_t page_start, eb_start, eb_end;
uint8_t* pc_real;
uint32_t opcode;

max_cycles = 0;

Expand All @@ -464,10 +468,11 @@ static void ppc_exec_until_inner(const uint32_t goal_addr)
exec_flags = 0;

pc_real = mmu_translate_imem(eb_start);
opcode = ppc_read_instruction(pc_real);

// interpret execution block
while (power_on && ppc_state.pc < eb_end) {
ppc_main_opcode();
ppc_main_opcode(opcode);
if (g_icycles++ >= max_cycles || exec_timer) {
max_cycles = process_events();
}
Expand All @@ -477,18 +482,19 @@ static void ppc_exec_until_inner(const uint32_t goal_addr)
eb_start = ppc_next_instruction_address;
if (!(exec_flags & EXEF_RFI) && (eb_start & PPC_PAGE_MASK) == page_start) {
pc_real += (int)eb_start - (int)ppc_state.pc;
ppc_set_cur_instruction(pc_real);
opcode = ppc_read_instruction(pc_real);
} else {
page_start = eb_start & PPC_PAGE_MASK;
eb_end = page_start + PPC_PAGE_SIZE - 1;
pc_real = mmu_translate_imem(eb_start);
opcode = ppc_read_instruction(pc_real);
}
ppc_state.pc = eb_start;
exec_flags = 0;
} else {
ppc_state.pc += 4;
pc_real += 4;
ppc_set_cur_instruction(pc_real);
opcode = ppc_read_instruction(pc_real);
}

if (ppc_state.pc == goal_addr)
Expand Down Expand Up @@ -519,6 +525,7 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size)
uint64_t max_cycles;
uint32_t page_start, eb_start, eb_end;
uint8_t* pc_real;
uint32_t opcode;

max_cycles = 0;

Expand All @@ -531,11 +538,12 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size)
exec_flags = 0;

pc_real = mmu_translate_imem(eb_start);
opcode = ppc_read_instruction(pc_real);

// interpret execution block
while (power_on && (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size)
&& (ppc_state.pc < eb_end)) {
ppc_main_opcode();
ppc_main_opcode(opcode);
if (g_icycles++ >= max_cycles || exec_timer) {
max_cycles = process_events();
}
Expand All @@ -545,18 +553,19 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size)
eb_start = ppc_next_instruction_address;
if (!(exec_flags & EXEF_RFI) && (eb_start & PPC_PAGE_MASK) == page_start) {
pc_real += (int)eb_start - (int)ppc_state.pc;
ppc_set_cur_instruction(pc_real);
opcode = ppc_read_instruction(pc_real);
} else {
page_start = eb_start & PPC_PAGE_MASK;
eb_end = page_start + PPC_PAGE_SIZE - 1;
pc_real = mmu_translate_imem(eb_start);
opcode = ppc_read_instruction(pc_real);
}
ppc_state.pc = eb_start;
exec_flags = 0;
} else {
ppc_state.pc += 4;
pc_real += 4;
ppc_set_cur_instruction(pc_real);
opcode = ppc_read_instruction(pc_real);
}
}
}
Expand Down
Loading

0 comments on commit 564c43c

Please sign in to comment.