Skip to content
Merged
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
9 changes: 9 additions & 0 deletions cpu/ppc/ppcemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,15 @@ extern bool include_601; // For non-PowerPC 601 emulation with 601 extras
extern bool is_altivec; // For Altivec Emulation
extern bool is_64bit; // For PowerPC G5 Emulation

enum class PPCPowMode : uint8_t {
None,
Unconditional,
HID0,
};

extern PPCPowMode ppc_pow_mode;
extern uint32_t ppc_pow_hid0_mask;

// Make execution deterministic (ignore external input, used a fixed date, etc.)
extern bool is_deterministic;

Expand Down
30 changes: 30 additions & 0 deletions cpu/ppc/ppcexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ MemCtrlBase* mem_ctrl_instance = 0;

bool is_601 = false;
bool include_601 = false;
PPCPowMode ppc_pow_mode = PPCPowMode::None;
uint32_t ppc_pow_hid0_mask = 0;

// 603/7xx HID0 power-saving mode bits. They are selected in HID0,
// then entered by setting MSR[POW] with mtmsr.
static constexpr uint32_t HID0_DOZE = 0x00800000;
static constexpr uint32_t HID0_NAP = 0x00400000;
static constexpr uint32_t HID0_SLEEP = 0x00200000;
static constexpr uint32_t HID0_POWER_SAVE_MASK = HID0_DOZE | HID0_NAP | HID0_SLEEP;

bool is_deterministic = false;

Expand Down Expand Up @@ -917,6 +926,27 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version, bool do_include_6
ppc_state.spr[SPR::PVR] = cpu_version;
is_601 = (cpu_version >> 16) == 1;
include_601 = !is_601 & do_include_601;
ppc_pow_mode = PPCPowMode::None;
ppc_pow_hid0_mask = 0;

switch (cpu_version) {
case PPC_VER::MPC603:
case PPC_VER::MPC603E:
case PPC_VER::MPC603EV:
case PPC_VER::MPC750:
// 603/7xx enter power-saving modes through HID0 doze/nap/sleep
// bits selected before MSR[POW] is set.
ppc_pow_mode = PPCPowMode::HID0;
ppc_pow_hid0_mask = HID0_POWER_SAVE_MASK;
break;
case PPC_VER::MPC604:
case PPC_VER::MPC604E:
// 604-family processors use MSR[POW] directly.
ppc_pow_mode = PPCPowMode::Unconditional;
break;
default:
break;
}

initialize_ppc_opcode_table();

Expand Down
31 changes: 20 additions & 11 deletions cpu/ppc/ppcopcodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
#include <vector>

// MPC750 HID0 power-saving mode bits. They are selected in HID0, then
// entered by setting MSR[POW] with mtmsr.
static constexpr uint32_t HID0_DOZE = 0x00800000;
static constexpr uint32_t HID0_NAP = 0x00400000;
static constexpr uint32_t HID0_SLEEP = 0x00200000;
static constexpr uint32_t HID0_POWER_SAVE_MASK = HID0_DOZE | HID0_NAP | HID0_SLEEP;

//Extract the registers desired and the values of the registers.

// Affects CR Field 0 - For integer operations
Expand Down Expand Up @@ -820,10 +813,26 @@ void dppc_interpreter::ppc_mtmsr(uint32_t opcode) {
dec_exception_pending = false;
//LOG_F(WARNING, "MTMSR: decrementer exception triggered");
ppc_exception_handler(Except_Type::EXC_DECR, 0);
} else if ((ppc_state.msr & MSR::POW) &&
(ppc_state.spr[SPR::HID0] & HID0_POWER_SAVE_MASK)) {
exec_flags |= EXEF_SLEEP;
ppc_next_instruction_address = (ppc_state.pc & 0xFFFFFFFCUL) + 4;
} else if (ppc_state.msr & MSR::POW) [[unlikely]] {
bool enter_sleep = false;

switch (ppc_pow_mode) {
case PPCPowMode::Unconditional:
enter_sleep = true;
break;
case PPCPowMode::HID0:
enter_sleep = (ppc_state.spr[SPR::HID0] & ppc_pow_hid0_mask) != 0;
break;
case PPCPowMode::None:
break;
}

if (enter_sleep) {
exec_flags |= EXEF_SLEEP;
ppc_next_instruction_address = (ppc_state.pc & 0xFFFFFFFCUL) + 4;
} else {
mmu_change_mode();
}
} else {
mmu_change_mode();
}
Expand Down
Loading