mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-24 12:30:05 +00:00
ppcmmu.c: restructure and clean up.
This commit is contained in:
parent
c5f45c6f9a
commit
2a79c9a63c
@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file PowerPC Memory management unit emulation. */
|
/** @file PowerPC Memory Management Unit emulation. */
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
- implement TLB
|
- implement TLB
|
||||||
@ -181,13 +181,6 @@ public:
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** Temporary TLB test variables. */
|
|
||||||
bool MemAccessType; // true - memory, false - I/O
|
|
||||||
bool Unaligned_crosspage = false;
|
|
||||||
uint64_t MemAddr = 0;
|
|
||||||
MMIODevice *Device = 0;
|
|
||||||
uint32_t DevOffset = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/** remember recently used physical memory regions for quicker translation. */
|
/** remember recently used physical memory regions for quicker translation. */
|
||||||
AddressMapEntry last_read_area = {0xFFFFFFFF, 0xFFFFFFFF};
|
AddressMapEntry last_read_area = {0xFFFFFFFF, 0xFFFFFFFF};
|
||||||
@ -215,16 +208,6 @@ static inline T read_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr)
|
|||||||
dmem_reads_total++;
|
dmem_reads_total++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!MemAccessType) {
|
|
||||||
LOG_F(ERROR, "TLB real memory access expected!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mru_rgn->mem_ptr + (addr - mru_rgn->start)) != (uint8_t *)MemAddr) {
|
|
||||||
LOG_F(ERROR, "TLB address mismatch! Expected: 0x%llx, got: 0x%llx",
|
|
||||||
(uint64_t)(mru_rgn->mem_ptr + (addr - mru_rgn->start)),
|
|
||||||
(uint64_t)MemAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(sizeof(T)) {
|
switch(sizeof(T)) {
|
||||||
case 1:
|
case 1:
|
||||||
return *(mru_rgn->mem_ptr + (addr - mru_rgn->start));
|
return *(mru_rgn->mem_ptr + (addr - mru_rgn->start));
|
||||||
@ -252,14 +235,6 @@ static inline T read_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr)
|
|||||||
#ifdef MMU_PROFILING
|
#ifdef MMU_PROFILING
|
||||||
iomem_reads_total++;
|
iomem_reads_total++;
|
||||||
#endif
|
#endif
|
||||||
if (MemAccessType) {
|
|
||||||
LOG_F(ERROR, "TLB I/O memory access expected!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mru_rgn->devobj != Device || (addr - mru_rgn->start) != DevOffset) {
|
|
||||||
LOG_F(ERROR, "TLB MMIO access mismatch! Expected: 0x%X, got: 0x%X",
|
|
||||||
addr - mru_rgn->start, DevOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (mru_rgn->devobj->read(mru_rgn->start,
|
return (mru_rgn->devobj->read(mru_rgn->start,
|
||||||
addr - mru_rgn->start, sizeof(T)));
|
addr - mru_rgn->start, sizeof(T)));
|
||||||
@ -287,20 +262,6 @@ static inline void write_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr, T val
|
|||||||
dmem_writes_total++;
|
dmem_writes_total++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
|
||||||
if (!MemAccessType) {
|
|
||||||
LOG_F(ERROR, "TLB real memory access expected!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_aligned && Unaligned_crosspage) {
|
|
||||||
LOG_F(WARNING, "Unaligned cross-page access ignored!");
|
|
||||||
} else if ((mru_rgn->mem_ptr + (addr - mru_rgn->start)) != (uint8_t *)MemAddr) {
|
|
||||||
LOG_F(ERROR, "TLB address mismatch! Expected: 0x%llx, got: 0x%llx",
|
|
||||||
(uint64_t)(mru_rgn->mem_ptr + (addr - mru_rgn->start)),
|
|
||||||
(uint64_t)MemAddr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch(sizeof(T)) {
|
switch(sizeof(T)) {
|
||||||
case 1:
|
case 1:
|
||||||
*(mru_rgn->mem_ptr + (addr - mru_rgn->start)) = value;
|
*(mru_rgn->mem_ptr + (addr - mru_rgn->start)) = value;
|
||||||
@ -333,17 +294,6 @@ static inline void write_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr, T val
|
|||||||
iomem_writes_total++;
|
iomem_writes_total++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
|
||||||
if (MemAccessType) {
|
|
||||||
LOG_F(ERROR, "TLB I/O memory access expected!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mru_rgn->devobj != Device || (addr - mru_rgn->start) != DevOffset) {
|
|
||||||
LOG_F(ERROR, "TLB MMIO access mismatch! Expected: 0x%X, got: 0x%X",
|
|
||||||
addr - mru_rgn->start, DevOffset);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mru_rgn->devobj->write(mru_rgn->start, addr - mru_rgn->start, value,
|
mru_rgn->devobj->write(mru_rgn->start, addr - mru_rgn->start, value,
|
||||||
sizeof(T));
|
sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
@ -375,6 +325,10 @@ void ppc_set_cur_instruction(const uint8_t* ptr) {
|
|||||||
bool gTLBFlushBatEntries = false;
|
bool gTLBFlushBatEntries = false;
|
||||||
bool gTLBFlushPatEntries = false;
|
bool gTLBFlushPatEntries = false;
|
||||||
|
|
||||||
|
// Forward declarations.
|
||||||
|
void tlb_flush_bat_entries();
|
||||||
|
void tlb_flush_pat_entries();
|
||||||
|
|
||||||
void ibat_update(uint32_t bat_reg) {
|
void ibat_update(uint32_t bat_reg) {
|
||||||
int upper_reg_num;
|
int upper_reg_num;
|
||||||
uint32_t bl, hi_mask;
|
uint32_t bl, hi_mask;
|
||||||
@ -527,7 +481,7 @@ static bool search_pteg(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PATResult page_address_translate(uint32_t la, bool is_instr_fetch,
|
static PATResult page_address_translation(uint32_t la, bool is_instr_fetch,
|
||||||
unsigned msr_pr, int is_write)
|
unsigned msr_pr, int is_write)
|
||||||
{
|
{
|
||||||
uint32_t sr_val, page_index, pteg_hash1, vsid, pte_word2;
|
uint32_t sr_val, page_index, pteg_hash1, vsid, pte_word2;
|
||||||
@ -598,7 +552,7 @@ static PATResult page_address_translate(uint32_t la, bool is_instr_fetch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** PowerPC-style MMU instruction address translation. */
|
/** PowerPC-style MMU instruction address translation. */
|
||||||
static uint32_t ppc_mmu_instr_translate(uint32_t la) {
|
static uint32_t mmu_instr_translation(uint32_t la) {
|
||||||
uint32_t pa; /* translated physical address */
|
uint32_t pa; /* translated physical address */
|
||||||
|
|
||||||
bool bat_hit = false;
|
bool bat_hit = false;
|
||||||
@ -631,7 +585,7 @@ static uint32_t ppc_mmu_instr_translate(uint32_t la) {
|
|||||||
|
|
||||||
/* page address translation */
|
/* page address translation */
|
||||||
if (!bat_hit) {
|
if (!bat_hit) {
|
||||||
PATResult pat_res = page_address_translate(la, true, msr_pr, 0);
|
PATResult pat_res = page_address_translation(la, true, msr_pr, 0);
|
||||||
pa = pat_res.phys;
|
pa = pat_res.phys;
|
||||||
|
|
||||||
#ifdef MMU_PROFILING
|
#ifdef MMU_PROFILING
|
||||||
@ -678,7 +632,7 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write) {
|
|||||||
|
|
||||||
/* page address translation */
|
/* page address translation */
|
||||||
if (!bat_hit) {
|
if (!bat_hit) {
|
||||||
PATResult pat_res = page_address_translate(la, false, msr_pr, is_write);
|
PATResult pat_res = page_address_translation(la, false, msr_pr, is_write);
|
||||||
pa = pat_res.phys;
|
pa = pat_res.phys;
|
||||||
|
|
||||||
#ifdef MMU_PROFILING
|
#ifdef MMU_PROFILING
|
||||||
@ -812,7 +766,7 @@ static TLBEntry* tlb2_target_entry(uint32_t gp_va)
|
|||||||
tlb_entry[2].lru_bits = 0x2;
|
tlb_entry[2].lru_bits = 0x2;
|
||||||
tlb_entry[3].lru_bits = 0x3;
|
tlb_entry[3].lru_bits = 0x3;
|
||||||
return &tlb_entry[3];
|
return &tlb_entry[3];
|
||||||
} else { // no invalid blocks, replace an existing one according with the hLRU policy
|
} else { // no free entries, replace an existing one according with the hLRU policy
|
||||||
#ifdef TLB_PROFILING
|
#ifdef TLB_PROFILING
|
||||||
num_entry_replacements++;
|
num_entry_replacements++;
|
||||||
#endif
|
#endif
|
||||||
@ -880,7 +834,7 @@ static TLBEntry* tlb2_refill(uint32_t guest_va, int is_write)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// page address translation
|
// page address translation
|
||||||
PATResult pat_res = page_address_translate(guest_va, false,
|
PATResult pat_res = page_address_translation(guest_va, false,
|
||||||
!!(ppc_state.msr & 0x4000), is_write);
|
!!(ppc_state.msr & 0x4000), is_write);
|
||||||
phys_addr = pat_res.phys;
|
phys_addr = pat_res.phys;
|
||||||
flags = TLBFlags::TLBE_FROM_PAT; // tell the world we come from
|
flags = TLBFlags::TLBE_FROM_PAT; // tell the world we come from
|
||||||
@ -1018,8 +972,6 @@ static inline uint64_t tlb_translate_addr(uint32_t guest_va)
|
|||||||
// look up address in the primary TLB
|
// look up address in the primary TLB
|
||||||
tlb1_entry = &pCurTLB1[(guest_va >> PAGE_SIZE_BITS) & tlb_size_mask];
|
tlb1_entry = &pCurTLB1[(guest_va >> PAGE_SIZE_BITS) & tlb_size_mask];
|
||||||
if (tlb1_entry->tag == tag) { // primary TLB hit -> fast path
|
if (tlb1_entry->tag == tag) { // primary TLB hit -> fast path
|
||||||
MemAccessType = true;
|
|
||||||
MemAddr = tlb1_entry->host_va_offset + guest_va;
|
|
||||||
return tlb1_entry->host_va_offset + guest_va;
|
return tlb1_entry->host_va_offset + guest_va;
|
||||||
} else { // primary TLB miss -> look up address in the secondary TLB
|
} else { // primary TLB miss -> look up address in the secondary TLB
|
||||||
tlb2_entry = &pCurTLB2[((guest_va >> PAGE_SIZE_BITS) & tlb_size_mask) * TLB2_WAYS];
|
tlb2_entry = &pCurTLB2[((guest_va >> PAGE_SIZE_BITS) & tlb_size_mask) * TLB2_WAYS];
|
||||||
@ -1060,13 +1012,8 @@ static inline uint64_t tlb_translate_addr(uint32_t guest_va)
|
|||||||
tlb1_entry->tag = tag;
|
tlb1_entry->tag = tag;
|
||||||
tlb1_entry->flags = tlb2_entry->flags;
|
tlb1_entry->flags = tlb2_entry->flags;
|
||||||
tlb1_entry->host_va_offset = tlb2_entry->host_va_offset;
|
tlb1_entry->host_va_offset = tlb2_entry->host_va_offset;
|
||||||
MemAccessType = true;
|
|
||||||
MemAddr = tlb1_entry->host_va_offset + guest_va;
|
|
||||||
return tlb1_entry->host_va_offset + guest_va;
|
return tlb1_entry->host_va_offset + guest_va;
|
||||||
} else { // an attempt to access a memory-mapped device
|
} else { // an attempt to access a memory-mapped device
|
||||||
MemAccessType = false;
|
|
||||||
Device = tlb2_entry->reg_desc->devobj;
|
|
||||||
DevOffset = guest_va - tlb2_entry->reg_desc->start;
|
|
||||||
return guest_va - tlb2_entry->reg_desc->start;
|
return guest_va - tlb2_entry->reg_desc->start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1236,7 +1183,6 @@ inline T mmu_read_vmem(uint32_t guest_va) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// explicitely instantiate all required mmu_read_vmem variants
|
// explicitely instantiate all required mmu_read_vmem variants
|
||||||
// to avoid linking errors
|
|
||||||
template uint8_t mmu_read_vmem<uint8_t>(uint32_t guest_va);
|
template uint8_t mmu_read_vmem<uint8_t>(uint32_t guest_va);
|
||||||
template uint16_t mmu_read_vmem<uint16_t>(uint32_t guest_va);
|
template uint16_t mmu_read_vmem<uint16_t>(uint32_t guest_va);
|
||||||
template uint32_t mmu_read_vmem<uint32_t>(uint32_t guest_va);
|
template uint32_t mmu_read_vmem<uint32_t>(uint32_t guest_va);
|
||||||
@ -1262,7 +1208,7 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
|
|||||||
}
|
}
|
||||||
if (!(tlb1_entry->flags & TLBFlags::PTE_SET_C)) {
|
if (!(tlb1_entry->flags & TLBFlags::PTE_SET_C)) {
|
||||||
// perform full page address translation to update PTE.C bit
|
// perform full page address translation to update PTE.C bit
|
||||||
PATResult pat_res = page_address_translate(guest_va, false,
|
PATResult pat_res = page_address_translation(guest_va, false,
|
||||||
!!(ppc_state.msr & 0x4000), true);
|
!!(ppc_state.msr & 0x4000), true);
|
||||||
tlb1_entry->flags |= TLBFlags::PTE_SET_C;
|
tlb1_entry->flags |= TLBFlags::PTE_SET_C;
|
||||||
|
|
||||||
@ -1273,8 +1219,6 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
host_va = (uint8_t *)(tlb1_entry->host_va_offset + guest_va);
|
host_va = (uint8_t *)(tlb1_entry->host_va_offset + guest_va);
|
||||||
MemAccessType = true;
|
|
||||||
MemAddr = (uint64_t)host_va;
|
|
||||||
} else {
|
} else {
|
||||||
// primary TLB miss -> look up address in the secondary TLB
|
// primary TLB miss -> look up address in the secondary TLB
|
||||||
tlb2_entry = lookup_secondary_tlb(guest_va, tag);
|
tlb2_entry = lookup_secondary_tlb(guest_va, tag);
|
||||||
@ -1293,8 +1237,6 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!(tlb2_entry->flags & TLBFlags::PAGE_WRITABLE)) {
|
if (!(tlb2_entry->flags & TLBFlags::PAGE_WRITABLE)) {
|
||||||
LOG_F(WARNING, "DSI Exception in mmu_write_vmem! PC=0x%08X", ppc_state.pc);
|
|
||||||
//return;
|
|
||||||
ppc_state.spr[SPR::DSISR] = 0x08000000 | (1 << 25);
|
ppc_state.spr[SPR::DSISR] = 0x08000000 | (1 << 25);
|
||||||
ppc_state.spr[SPR::DAR] = guest_va;
|
ppc_state.spr[SPR::DAR] = guest_va;
|
||||||
mmu_exception_handler(Except_Type::EXC_DSI, 0);
|
mmu_exception_handler(Except_Type::EXC_DSI, 0);
|
||||||
@ -1302,7 +1244,7 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
|
|||||||
|
|
||||||
if (!(tlb2_entry->flags & TLBFlags::PTE_SET_C)) {
|
if (!(tlb2_entry->flags & TLBFlags::PTE_SET_C)) {
|
||||||
// perform full page address translation to update PTE.C bit
|
// perform full page address translation to update PTE.C bit
|
||||||
PATResult pat_res = page_address_translate(guest_va, false,
|
PATResult pat_res = page_address_translation(guest_va, false,
|
||||||
!!(ppc_state.msr & 0x4000), true);
|
!!(ppc_state.msr & 0x4000), true);
|
||||||
tlb2_entry->flags |= TLBFlags::PTE_SET_C;
|
tlb2_entry->flags |= TLBFlags::PTE_SET_C;
|
||||||
}
|
}
|
||||||
@ -1313,17 +1255,12 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
|
|||||||
tlb1_entry->flags = tlb2_entry->flags;
|
tlb1_entry->flags = tlb2_entry->flags;
|
||||||
tlb1_entry->host_va_offset = tlb2_entry->host_va_offset;
|
tlb1_entry->host_va_offset = tlb2_entry->host_va_offset;
|
||||||
host_va = (uint8_t *)(tlb1_entry->host_va_offset + guest_va);
|
host_va = (uint8_t *)(tlb1_entry->host_va_offset + guest_va);
|
||||||
//MemAccessType = true;
|
|
||||||
//MemAddr = (uint64_t)host_va;
|
|
||||||
} else { // otherwise, it's an access to a memory-mapped device
|
} else { // otherwise, it's an access to a memory-mapped device
|
||||||
#ifdef MMU_PROFILING
|
#ifdef MMU_PROFILING
|
||||||
iomem_writes_total++;
|
iomem_writes_total++;
|
||||||
#endif
|
#endif
|
||||||
tlb2_entry->reg_desc->devobj->write(tlb2_entry->reg_desc->start,
|
tlb2_entry->reg_desc->devobj->write(tlb2_entry->reg_desc->start,
|
||||||
guest_va - tlb2_entry->reg_desc->start, value, sizeof(T));
|
guest_va - tlb2_entry->reg_desc->start, value, sizeof(T));
|
||||||
//MemAccessType = false;
|
|
||||||
//Device = tlb2_entry->reg_desc->devobj;
|
|
||||||
//DevOffset = guest_va - tlb2_entry->reg_desc->start;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1338,7 +1275,6 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
|
||||||
// handle aligned memory accesses
|
// handle aligned memory accesses
|
||||||
switch(sizeof(T)) {
|
switch(sizeof(T)) {
|
||||||
case 1:
|
case 1:
|
||||||
@ -1354,11 +1290,9 @@ inline void mmu_write_vmem(uint32_t guest_va, T value) {
|
|||||||
WRITE_QWORD_BE_A(host_va, value);
|
WRITE_QWORD_BE_A(host_va, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// explicitely instantiate all required mmu_write_vmem variants
|
// explicitely instantiate all required mmu_write_vmem variants
|
||||||
// to avoid linking errors
|
|
||||||
template void mmu_write_vmem<uint8_t>(uint32_t guest_va, uint8_t value);
|
template void mmu_write_vmem<uint8_t>(uint32_t guest_va, uint8_t value);
|
||||||
template void mmu_write_vmem<uint16_t>(uint32_t guest_va, uint16_t value);
|
template void mmu_write_vmem<uint16_t>(uint32_t guest_va, uint16_t value);
|
||||||
template void mmu_write_vmem<uint32_t>(uint32_t guest_va, uint32_t value);
|
template void mmu_write_vmem<uint32_t>(uint32_t guest_va, uint32_t value);
|
||||||
@ -1556,7 +1490,7 @@ uint8_t* quickinstruction_translate(uint32_t addr) {
|
|||||||
|
|
||||||
/* perform instruction address translation if enabled */
|
/* perform instruction address translation if enabled */
|
||||||
if (ppc_state.msr & 0x20) {
|
if (ppc_state.msr & 0x20) {
|
||||||
addr = ppc_mmu_instr_translate(addr);
|
addr = mmu_instr_translation(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr >= last_exec_area.start && addr <= last_exec_area.end) {
|
if (addr >= last_exec_area.start && addr <= last_exec_area.end) {
|
||||||
|
@ -19,10 +19,10 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// The opcodes for the processor - ppcopcodes.cpp
|
/** @file PowerPC Memory Management Unit definitions. */
|
||||||
|
|
||||||
#ifndef PPCMEMORY_H
|
#ifndef PPCMMU_H
|
||||||
#define PPCMEMORY_H
|
#define PPCMMU_H
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
@ -93,8 +93,6 @@ extern uint8_t* mmu_get_dma_mem(uint32_t addr, uint32_t size);
|
|||||||
extern void mmu_change_mode(void);
|
extern void mmu_change_mode(void);
|
||||||
extern void mmu_pat_ctx_changed();
|
extern void mmu_pat_ctx_changed();
|
||||||
extern void tlb_flush_entry(uint32_t ea);
|
extern void tlb_flush_entry(uint32_t ea);
|
||||||
extern void tlb_flush_bat_entries();
|
|
||||||
extern void tlb_flush_pat_entries();
|
|
||||||
|
|
||||||
extern void ppc_set_cur_instruction(const uint8_t* ptr);
|
extern void ppc_set_cur_instruction(const uint8_t* ptr);
|
||||||
extern void mem_write_byte(uint32_t addr, uint8_t value);
|
extern void mem_write_byte(uint32_t addr, uint8_t value);
|
||||||
@ -113,4 +111,4 @@ extern T mmu_read_vmem(uint32_t guest_va);
|
|||||||
template <class T>
|
template <class T>
|
||||||
extern void mmu_write_vmem(uint32_t guest_va, T value);
|
extern void mmu_write_vmem(uint32_t guest_va, T value);
|
||||||
|
|
||||||
#endif // PPCMEMORY_H
|
#endif // PPCMMU_H
|
||||||
|
@ -873,7 +873,6 @@ void dppc_interpreter::ppc_mtspr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ref_spr == SPR::SDR1) {
|
if (ref_spr == SPR::SDR1) {
|
||||||
LOG_F(INFO, "SDR1 changed to 0x%08X", ppc_state.spr[SPR::SDR1]);
|
|
||||||
mmu_pat_ctx_changed();
|
mmu_pat_ctx_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user