Implement SoftTLB for writes.

This commit is contained in:
Maxim Poliakovski 2021-08-03 16:01:32 +02:00
parent 4f3dd797be
commit 089645e830
7 changed files with 546 additions and 165 deletions

View File

@ -148,22 +148,26 @@ void dppc_interpreter::power_lscbx() {
if (match_found == false) { if (match_found == false) {
switch (shift_amount) { switch (shift_amount) {
case 0: case 0:
return_value = mem_grab_byte(ppc_effective_address); return_value = mmu_read_vmem<uint8_t>(ppc_effective_address);
//return_value = mem_grab_byte(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0x00FFFFFF) | (return_value << 24); ppc_result_d = (ppc_result_d & 0x00FFFFFF) | (return_value << 24);
ppc_store_result_regd(); ppc_store_result_regd();
break; break;
case 1: case 1:
return_value = mem_grab_byte(ppc_effective_address); return_value = mmu_read_vmem<uint8_t>(ppc_effective_address);
//return_value = mem_grab_byte(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16); ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16);
ppc_store_result_regd(); ppc_store_result_regd();
break; break;
case 2: case 2:
return_value = mem_grab_byte(ppc_effective_address); return_value = mmu_read_vmem<uint8_t>(ppc_effective_address);
//return_value = mem_grab_byte(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8); ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8);
ppc_store_result_regd(); ppc_store_result_regd();
break; break;
case 3: case 3:
return_value = mem_grab_byte(ppc_effective_address); return_value = mmu_read_vmem<uint8_t>(ppc_effective_address);
//return_value = mem_grab_byte(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value; ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value;
ppc_store_result_regd(); ppc_store_result_regd();
break; break;
@ -494,4 +498,4 @@ void dppc_interpreter::power_srlq() {
void dppc_interpreter::power_srq() { void dppc_interpreter::power_srq() {
LOG_F(WARNING, "OOPS! Placeholder for srq!!! \n"); LOG_F(WARNING, "OOPS! Placeholder for srq!!! \n");
} }

View File

@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "devices/memctrlbase.h" #include "devices/memctrlbase.h"
#include "endianswap.h" #include "endianswap.h"
#include <cinttypes> #include <cinttypes>
#include <functional>
#include <setjmp.h> #include <setjmp.h>
#include <string> #include <string>
@ -301,6 +302,9 @@ void ppc_fp_changecrf1();
// MEMORY DECLARATIONS // MEMORY DECLARATIONS
extern MemCtrlBase* mem_ctrl_instance; extern MemCtrlBase* mem_ctrl_instance;
//typedef std::function<void()> CtxSyncCallback;
extern void add_ctx_sync_action(const std::function<void()> &);
// The functions used by the PowerPC processor // The functions used by the PowerPC processor
namespace dppc_interpreter { namespace dppc_interpreter {
extern void ppc_bcctr(); extern void ppc_bcctr();

View File

@ -674,11 +674,11 @@ void dppc_interpreter::ppc_fctiw() {
if (std::isnan(val_reg_b)) { if (std::isnan(val_reg_b)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x1000100; ppc_state.fpscr |= 0x1000100;
} }
else if (val_reg_b > static_cast<double>(0x7fffffff)) { else if (val_reg_b > static_cast<double>(0x7fffffff)) {
ppc_state.fpr[reg_d].int64_r = 0x7fffffff; ppc_state.fpr[reg_d].int64_r = 0x7fffffff;
ppc_state.fpscr |= 0x100; ppc_state.fpscr |= 0x100;
} }
else if (val_reg_b < -static_cast<double>(0x80000000)) { else if (val_reg_b < -static_cast<double>(0x80000000)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x100; ppc_state.fpscr |= 0x100;
@ -696,7 +696,7 @@ void dppc_interpreter::ppc_fctiw() {
} }
ppc_store_dfpresult_int(reg_d); ppc_store_dfpresult_int(reg_d);
} }
if (rc_flag) if (rc_flag)
@ -710,15 +710,15 @@ void dppc_interpreter::ppc_fctiwz() {
if (std::isnan(val_reg_b)) { if (std::isnan(val_reg_b)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x1000100; ppc_state.fpscr |= 0x1000100;
} }
else if (val_reg_b > static_cast<double>(0x7fffffff)) { else if (val_reg_b > static_cast<double>(0x7fffffff)) {
ppc_state.fpr[reg_d].int64_r = 0x7fffffff; ppc_state.fpr[reg_d].int64_r = 0x7fffffff;
ppc_state.fpscr |= 0x100; ppc_state.fpscr |= 0x100;
} }
else if (val_reg_b < -static_cast<double>(0x80000000)) { else if (val_reg_b < -static_cast<double>(0x80000000)) {
ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpr[reg_d].int64_r = 0x80000000;
ppc_state.fpscr |= 0x100; ppc_state.fpscr |= 0x100;
} }
else { else {
ppc_result64_d = round_to_zero(val_reg_b); ppc_result64_d = round_to_zero(val_reg_b);
@ -735,7 +735,8 @@ void dppc_interpreter::ppc_lfs() {
ppc_grab_regsfpdia(); ppc_grab_regsfpdia();
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a) ? val_reg_a : 0; ppc_effective_address += (reg_a) ? val_reg_a : 0;
ppc_result64_d = mem_grab_dword(ppc_effective_address); ppc_result64_d = mmu_read_vmem<uint32_t>(ppc_effective_address);
//ppc_result64_d = mem_grab_dword(ppc_effective_address);
ppc_store_sfpresult_int(reg_d); ppc_store_sfpresult_int(reg_d);
} }
@ -745,7 +746,8 @@ void dppc_interpreter::ppc_lfsu() {
if (reg_a) { if (reg_a) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a) ? val_reg_a : 0; ppc_effective_address += (reg_a) ? val_reg_a : 0;
ppc_result64_d = mem_grab_dword(ppc_effective_address); ppc_result64_d = mmu_read_vmem<uint32_t>(ppc_effective_address);
//ppc_result64_d = mem_grab_dword(ppc_effective_address);
ppc_store_sfpresult_int(reg_d); ppc_store_sfpresult_int(reg_d);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
@ -756,7 +758,8 @@ void dppc_interpreter::ppc_lfsu() {
void dppc_interpreter::ppc_lfsx() { void dppc_interpreter::ppc_lfsx() {
ppc_grab_regsfpdiab(); ppc_grab_regsfpdiab();
ppc_effective_address = (reg_a) ? val_reg_a + val_reg_b : val_reg_b; ppc_effective_address = (reg_a) ? val_reg_a + val_reg_b : val_reg_b;
ppc_result64_d = mem_grab_dword(ppc_effective_address); ppc_result64_d = mmu_read_vmem<uint32_t>(ppc_effective_address);
//ppc_result64_d = mem_grab_dword(ppc_effective_address);
ppc_store_sfpresult_int(reg_d); ppc_store_sfpresult_int(reg_d);
} }
@ -764,7 +767,8 @@ void dppc_interpreter::ppc_lfsux() {
ppc_grab_regsfpdiab(); ppc_grab_regsfpdiab();
if (reg_a) { if (reg_a) {
ppc_effective_address = val_reg_a + val_reg_b; ppc_effective_address = val_reg_a + val_reg_b;
ppc_result64_d = mem_grab_dword(ppc_effective_address); ppc_result64_d = mmu_read_vmem<uint32_t>(ppc_effective_address);
//ppc_result64_d = mem_grab_dword(ppc_effective_address);
ppc_store_sfpresult_int(reg_d); ppc_store_sfpresult_int(reg_d);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
@ -820,7 +824,8 @@ void dppc_interpreter::ppc_stfs() {
ppc_grab_regsfpsia(); ppc_grab_regsfpsia();
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a) ? val_reg_a : 0; ppc_effective_address += (reg_a) ? val_reg_a : 0;
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r)); mmu_write_vmem<uint32_t>(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
//mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
} }
void dppc_interpreter::ppc_stfsu() { void dppc_interpreter::ppc_stfsu() {
@ -828,7 +833,8 @@ void dppc_interpreter::ppc_stfsu() {
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += val_reg_a; ppc_effective_address += val_reg_a;
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r)); mmu_write_vmem<uint32_t>(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
//mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -838,14 +844,16 @@ void dppc_interpreter::ppc_stfsu() {
void dppc_interpreter::ppc_stfsx() { void dppc_interpreter::ppc_stfsx() {
ppc_grab_regsfpsiab(); ppc_grab_regsfpsiab();
ppc_effective_address = (reg_a) ? val_reg_a + val_reg_b : val_reg_b; ppc_effective_address = (reg_a) ? val_reg_a + val_reg_b : val_reg_b;
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r)); mmu_write_vmem<uint32_t>(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
//mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
} }
void dppc_interpreter::ppc_stfsux() { void dppc_interpreter::ppc_stfsux() {
ppc_grab_regsfpsiab(); ppc_grab_regsfpsiab();
if (reg_a) { if (reg_a) {
ppc_effective_address = val_reg_a + val_reg_b; ppc_effective_address = val_reg_a + val_reg_b;
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r)); mmu_write_vmem<uint32_t>(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
//mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -856,7 +864,8 @@ void dppc_interpreter::ppc_stfd() {
ppc_grab_regsfpsia(); ppc_grab_regsfpsia();
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a) ? val_reg_a : 0; ppc_effective_address += (reg_a) ? val_reg_a : 0;
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r); mmu_write_vmem<uint64_t>(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
//mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
} }
void dppc_interpreter::ppc_stfdu() { void dppc_interpreter::ppc_stfdu() {
@ -864,7 +873,8 @@ void dppc_interpreter::ppc_stfdu() {
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += val_reg_a; ppc_effective_address += val_reg_a;
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r); mmu_write_vmem<uint64_t>(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
//mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -874,14 +884,16 @@ void dppc_interpreter::ppc_stfdu() {
void dppc_interpreter::ppc_stfdx() { void dppc_interpreter::ppc_stfdx() {
ppc_grab_regsfpsiab(); ppc_grab_regsfpsiab();
ppc_effective_address = (reg_a) ? val_reg_a + val_reg_b : val_reg_b; ppc_effective_address = (reg_a) ? val_reg_a + val_reg_b : val_reg_b;
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r); mmu_write_vmem<uint64_t>(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
//mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
} }
void dppc_interpreter::ppc_stfdux() { void dppc_interpreter::ppc_stfdux() {
ppc_grab_regsfpsiab(); ppc_grab_regsfpsiab();
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = val_reg_a + val_reg_b; ppc_effective_address = val_reg_a + val_reg_b;
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r); mmu_write_vmem<uint64_t>(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
//mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -891,7 +903,8 @@ void dppc_interpreter::ppc_stfdux() {
void dppc_interpreter::ppc_stfiwx() { void dppc_interpreter::ppc_stfiwx() {
ppc_grab_regsfpsiab(); ppc_grab_regsfpsiab();
ppc_effective_address = (reg_a) ? val_reg_a + val_reg_b : val_reg_b; ppc_effective_address = (reg_a) ? val_reg_a + val_reg_b : val_reg_b;
mem_write_dword(ppc_effective_address, (uint32_t)(ppc_state.fpr[reg_s].int64_r)); mmu_write_vmem<uint32_t>(ppc_effective_address, (uint32_t)(ppc_state.fpr[reg_s].int64_r));
//mem_write_dword(ppc_effective_address, (uint32_t)(ppc_state.fpr[reg_s].int64_r));
} }
// Floating Point Register Transfer // Floating Point Register Transfer

View File

@ -137,6 +137,7 @@ public:
/** Temporary TLB test variables. */ /** Temporary TLB test variables. */
bool MemAccessType; // true - memory, false - I/O bool MemAccessType; // true - memory, false - I/O
bool Unaligned_crosspage = false;
uint64_t MemAddr = 0; uint64_t MemAddr = 0;
MMIODevice *Device = 0; MMIODevice *Device = 0;
uint32_t DevOffset = 0; uint32_t DevOffset = 0;
@ -239,6 +240,21 @@ static inline void write_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr, T val
#ifdef MMU_PROFILING #ifdef MMU_PROFILING
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;
@ -270,6 +286,18 @@ static inline void write_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr, T val
#ifdef MMU_PROFILING #ifdef MMU_PROFILING
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 {
@ -298,6 +326,9 @@ void ppc_set_cur_instruction(const uint8_t* ptr) {
ppc_cur_instruction = READ_DWORD_BE_A(ptr); ppc_cur_instruction = READ_DWORD_BE_A(ptr);
} }
bool gTLBFlushBatEntries = false;
bool gTLBFlushPatEntries = false;
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;
@ -335,6 +366,19 @@ void dbat_update(uint32_t bat_reg) {
bat_entry->hi_mask = hi_mask; bat_entry->hi_mask = hi_mask;
bat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & hi_mask; bat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & hi_mask;
bat_entry->bepi = ppc_state.spr[upper_reg_num] & hi_mask; bat_entry->bepi = ppc_state.spr[upper_reg_num] & hi_mask;
if (!gTLBFlushBatEntries) {
gTLBFlushBatEntries = true;
add_ctx_sync_action(&tlb_flush_bat_entries);
}
}
}
void mmu_pat_ctx_changed()
{
if (!gTLBFlushPatEntries) {
gTLBFlushPatEntries = true;
add_ctx_sync_action(&tlb_flush_pat_entries);
} }
} }
@ -437,7 +481,9 @@ static bool search_pteg(
return false; return false;
} }
static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch, unsigned msr_pr, int is_write) { static PATResult page_address_translate(uint32_t la, bool is_instr_fetch,
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;
unsigned key, pp; unsigned key, pp;
uint8_t* pte_addr; uint8_t* pte_addr;
@ -497,8 +543,12 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch, unsigne
pte_addr[7] |= 0x80; pte_addr[7] |= 0x80;
} }
/* return physical address */ /* return physical address, access protection and C status */
return ((pte_word2 & 0xFFFFF000) | (la & 0x00000FFF)); return PATResult{
((pte_word2 & 0xFFFFF000) | (la & 0x00000FFF)),
static_cast<uint8_t>((key << 2) | pp),
static_cast<uint8_t>(pte_word2 & 0x80)
};
} }
/** PowerPC-style MMU instruction address translation. */ /** PowerPC-style MMU instruction address translation. */
@ -535,7 +585,8 @@ static uint32_t ppc_mmu_instr_translate(uint32_t la) {
/* page address translation */ /* page address translation */
if (!bat_hit) { if (!bat_hit) {
pa = page_address_translate(la, true, msr_pr, 0); PATResult pat_res = page_address_translate(la, true, msr_pr, 0);
pa = pat_res.phys;
#ifdef MMU_PROFILING #ifdef MMU_PROFILING
ptab_transl_total++; ptab_transl_total++;
@ -581,7 +632,8 @@ 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) {
pa = page_address_translate(la, false, msr_pr, is_write); PATResult pat_res = page_address_translate(la, false, msr_pr, is_write);
pa = pat_res.phys;
#ifdef MMU_PROFILING #ifdef MMU_PROFILING
ptab_transl_total++; ptab_transl_total++;
@ -635,73 +687,6 @@ static void mem_write_unaligned(uint32_t addr, uint32_t value, uint32_t size) {
} }
} }
void mem_write_byte(uint32_t addr, uint8_t value) {
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
write_phys_mem<uint8_t, true>(&last_write_area, addr, value);
}
void mem_write_word(uint32_t addr, uint16_t value) {
if (addr & 1) {
mem_write_unaligned(addr, value, 2);
return;
}
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
write_phys_mem<uint16_t, true>(&last_write_area, addr, value);
}
void mem_write_dword(uint32_t addr, uint32_t value) {
if (addr & 3) {
mem_write_unaligned(addr, value, 4);
return;
}
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
write_phys_mem<uint32_t, true>(&last_write_area, addr, value);
}
void mem_write_qword(uint32_t addr, uint64_t value) {
if (addr & 7) {
LOG_F(ERROR, "SOS! Attempt to write unaligned QWORD to 0x%08X\n", addr);
exit(-1); // FIXME!
}
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
write_phys_mem<uint64_t, true>(&last_write_area, addr, value);
}
#define PAGE_SIZE_BITS 12
#define TLB_SIZE 4096
#define TLB2_WAYS 4
#define TLB_INVALID_TAG 0xFFFFFFFF
typedef struct TLBEntry {
uint32_t tag;
uint16_t flags;
uint16_t lru_bits;
union {
int64_t host_va_offset;
AddressMapEntry* reg_desc;
};
} TLBEntry;
// primary TLB for all MMU modes // primary TLB for all MMU modes
static std::array<TLBEntry, TLB_SIZE> mode1_tlb1; static std::array<TLBEntry, TLB_SIZE> mode1_tlb1;
static std::array<TLBEntry, TLB_SIZE> mode2_tlb1; static std::array<TLBEntry, TLB_SIZE> mode2_tlb1;
@ -721,13 +706,13 @@ uint32_t tlb_size_mask = TLB_SIZE - 1;
uint64_t UnmappedVal = -1ULL; uint64_t UnmappedVal = -1ULL;
TLBEntry UnmappedMem = {TLB_INVALID_TAG, 0, 0, 0}; TLBEntry UnmappedMem = {TLB_INVALID_TAG, 0, 0, 0};
uint8_t MMUMode = {0xFF}; uint8_t CurMMUMode = {0xFF}; // current MMU mode
void mmu_change_mode() void mmu_change_mode()
{ {
uint8_t mmu_mode = ((ppc_state.msr >> 3) & 0x2) | ((ppc_state.msr >> 14) & 1); uint8_t mmu_mode = ((ppc_state.msr >> 3) & 0x2) | ((ppc_state.msr >> 14) & 1);
if (MMUMode != mmu_mode) { if (CurMMUMode != mmu_mode) {
switch(mmu_mode) { switch(mmu_mode) {
case 0: // real address mode case 0: // real address mode
pCurTLB1 = &mode1_tlb1[0]; pCurTLB1 = &mode1_tlb1[0];
@ -742,7 +727,7 @@ void mmu_change_mode()
pCurTLB2 = &mode3_tlb2[0]; pCurTLB2 = &mode3_tlb2[0];
break; break;
} }
MMUMode = mmu_mode; CurMMUMode = mmu_mode;
} }
} }
@ -817,6 +802,7 @@ static TLBEntry* tlb2_target_entry(uint32_t gp_va)
static TLBEntry* tlb2_refill(uint32_t guest_va, int is_write) static TLBEntry* tlb2_refill(uint32_t guest_va, int is_write)
{ {
uint32_t phys_addr; uint32_t phys_addr;
uint16_t flags = 0;
TLBEntry *tlb_entry; TLBEntry *tlb_entry;
const uint32_t tag = guest_va & ~0xFFFUL; const uint32_t tag = guest_va & ~0xFFFUL;
@ -828,18 +814,40 @@ static TLBEntry* tlb2_refill(uint32_t guest_va, int is_write)
if (bat_res.hit) { if (bat_res.hit) {
// check block protection // check block protection
if (!bat_res.prot || ((bat_res.prot & 1) && is_write)) { if (!bat_res.prot || ((bat_res.prot & 1) && is_write)) {
LOG_F(WARNING, "BAT DSI exception in TLB2 refill!");
LOG_F(WARNING, "Attempt to write to read-only region, LA=0x%08X, PC=0x%08X!", guest_va, ppc_state.pc);
//UnmappedMem.tag = tag;
//UnmappedMem.host_va_offset = (int64_t)(&UnmappedVal) - guest_va;
//return &UnmappedMem;
ppc_state.spr[SPR::DSISR] = 0x08000000 | (is_write << 25); ppc_state.spr[SPR::DSISR] = 0x08000000 | (is_write << 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);
} }
phys_addr = bat_res.phys; phys_addr = bat_res.phys;
flags = TLBFlags::PTE_SET_C; // prevent PTE.C updates for BAT
flags |= TLBFlags::TLBE_FROM_BAT; // tell the world we come from
if (bat_res.prot == 2) {
flags |= TLBFlags::PAGE_WRITABLE;
}
} else { } else {
// page address translation // page address translation
phys_addr = page_address_translate(guest_va, false, PATResult pat_res = page_address_translate(guest_va, false,
!!(ppc_state.msr & 0x4000), is_write); !!(ppc_state.msr & 0x4000), is_write);
phys_addr = pat_res.phys;
flags = TLBFlags::TLBE_FROM_PAT; // tell the world we come from
if (pat_res.prot <= 2 || pat_res.prot == 6) {
flags |= TLBFlags::PAGE_WRITABLE;
}
if (is_write || pat_res.pte_c_status) {
// C-bit of the PTE is already set so the TLB logic
// doesn't need to update it anymore
flags |= TLBFlags::PTE_SET_C;
}
} }
} else { } else { // data translation disabled
phys_addr = guest_va; phys_addr = guest_va;
flags = TLBFlags::PTE_SET_C; // no PTE.C updates in real addressing mode
flags |= TLBFlags::PAGE_WRITABLE; // assume physical pages are writable
} }
// look up host virtual address // look up host virtual address
@ -848,11 +856,11 @@ static TLBEntry* tlb2_refill(uint32_t guest_va, int is_write)
// refill the secondary TLB // refill the secondary TLB
tlb_entry = tlb2_target_entry(tag); tlb_entry = tlb2_target_entry(tag);
tlb_entry->tag = tag; tlb_entry->tag = tag;
if (reg_desc->type & RT_MMIO) { if (reg_desc->type & RT_MMIO) { // MMIO region
tlb_entry->flags = 2; // MMIO region tlb_entry->flags = flags | TLBFlags::PAGE_IO;
tlb_entry->reg_desc = reg_desc; tlb_entry->reg_desc = reg_desc;
} else { } else { // memory region backed by host memory
tlb_entry->flags = 1; // memory region backed by host memory tlb_entry->flags = flags | TLBFlags::PAGE_MEM;
tlb_entry->host_va_offset = (int64_t)reg_desc->mem_ptr - guest_va + tlb_entry->host_va_offset = (int64_t)reg_desc->mem_ptr - guest_va +
(phys_addr - reg_desc->start); (phys_addr - reg_desc->start);
} }
@ -865,7 +873,7 @@ static TLBEntry* tlb2_refill(uint32_t guest_va, int is_write)
} }
} }
void flush_tlb_entry(uint32_t ea) void tlb_flush_entry(uint32_t ea)
{ {
TLBEntry *tlb_entry, *tlb1, *tlb2; TLBEntry *tlb_entry, *tlb1, *tlb2;
@ -878,12 +886,12 @@ void flush_tlb_entry(uint32_t ea)
tlb2 = &mode1_tlb2[0]; tlb2 = &mode1_tlb2[0];
break; break;
case 1: case 1:
tlb1 = &mode1_tlb1[0]; tlb1 = &mode2_tlb1[0];
tlb2 = &mode1_tlb2[0]; tlb2 = &mode2_tlb2[0];
break; break;
case 2: case 2:
tlb1 = &mode1_tlb1[0]; tlb1 = &mode3_tlb1[0];
tlb2 = &mode1_tlb2[0]; tlb2 = &mode3_tlb2[0];
break; break;
} }
@ -905,6 +913,53 @@ void flush_tlb_entry(uint32_t ea)
} }
} }
void tlb_flush_entries(TLBFlags type)
{
int i;
// Flush BAT entries from the primary TLBs
for (i = 0; i < TLB_SIZE; i++) {
if (mode2_tlb1[i].flags & type) {
mode2_tlb1[i].tag = TLB_INVALID_TAG;
}
if (mode3_tlb1[i].flags & type) {
mode3_tlb1[i].tag = TLB_INVALID_TAG;
}
}
// Flush BAT entries from the secondary TLBs
for (i = 0; i < TLB_SIZE * TLB2_WAYS; i++) {
if (mode2_tlb2[i].flags & type) {
mode2_tlb2[i].tag = TLB_INVALID_TAG;
}
if (mode3_tlb2[i].flags & type) {
mode3_tlb2[i].tag = TLB_INVALID_TAG;
}
}
}
void tlb_flush_bat_entries()
{
if (!gTLBFlushBatEntries)
return;
tlb_flush_entries(TLBE_FROM_BAT);
gTLBFlushBatEntries = false;
}
void tlb_flush_pat_entries()
{
if (!gTLBFlushPatEntries)
return;
tlb_flush_entries(TLBE_FROM_PAT);
gTLBFlushPatEntries = false;
}
static inline uint64_t tlb_translate_addr(uint32_t guest_va) static inline uint64_t tlb_translate_addr(uint32_t guest_va)
{ {
TLBEntry *tlb1_entry, *tlb2_entry; TLBEntry *tlb1_entry, *tlb2_entry;
@ -951,10 +1006,10 @@ static inline uint64_t tlb_translate_addr(uint32_t guest_va)
tlb2_entry = tlb2_refill(guest_va, 0); tlb2_entry = tlb2_refill(guest_va, 0);
} }
if (tlb2_entry->flags & 1) { // is it a real memory region? if (tlb2_entry->flags & TLBFlags::PAGE_MEM) { // is it a real memory region?
// refill the primary TLB // refill the primary TLB
tlb1_entry->tag = tag; tlb1_entry->tag = tag;
tlb1_entry->flags = 1; 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; MemAccessType = true;
MemAddr = tlb1_entry->host_va_offset + guest_va; MemAddr = tlb1_entry->host_va_offset + guest_va;
@ -1056,7 +1111,10 @@ static inline TLBEntry * lookup_secondary_tlb(uint32_t guest_va, uint32_t tag) {
return tlb_entry; return tlb_entry;
} }
// Forward declarations.
static uint32_t read_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t size); static uint32_t read_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t size);
static void write_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t value,
uint32_t size);
template <class T> template <class T>
inline T mmu_read_vmem(uint32_t guest_va) { inline T mmu_read_vmem(uint32_t guest_va) {
@ -1078,10 +1136,10 @@ inline T mmu_read_vmem(uint32_t guest_va) {
tlb2_entry = tlb2_refill(guest_va, 0); tlb2_entry = tlb2_refill(guest_va, 0);
} }
if (tlb2_entry->flags & 1) { // is it a real memory region? if (tlb2_entry->flags & TLBFlags::PAGE_MEM) { // is it a real memory region?
// refill the primary TLB // refill the primary TLB
tlb1_entry->tag = tag; tlb1_entry->tag = tag;
tlb1_entry->flags = 1; 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);
} else { // otherwise, it's an access to a memory-mapped device } else { // otherwise, it's an access to a memory-mapped device
@ -1117,6 +1175,110 @@ 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);
template uint64_t mmu_read_vmem<uint64_t>(uint32_t guest_va); template uint64_t mmu_read_vmem<uint64_t>(uint32_t guest_va);
template <class T>
inline void mmu_write_vmem(uint32_t guest_va, T value) {
TLBEntry *tlb1_entry, *tlb2_entry;
uint8_t *host_va;
const uint32_t tag = guest_va & ~0xFFFUL;
// look up guest virtual address in the primary TLB
tlb1_entry = &pCurTLB1[(guest_va >> PAGE_SIZE_BITS) & tlb_size_mask];
if (tlb1_entry->tag == tag) { // primary TLB hit -> fast path
if (!(tlb1_entry->flags & TLBFlags::PAGE_WRITABLE)) {
ppc_state.spr[SPR::DSISR] = 0x08000000 | (1 << 25);
ppc_state.spr[SPR::DAR] = guest_va;
mmu_exception_handler(Except_Type::EXC_DSI, 0);
}
if (!(tlb1_entry->flags & TLBFlags::PTE_SET_C)) {
// perform full page address translation to update PTE.C bit
PATResult pat_res = page_address_translate(guest_va, false,
!!(ppc_state.msr & 0x4000), true);
tlb1_entry->flags |= TLBFlags::PTE_SET_C;
// don't forget to update the secondary TLB as well
tlb2_entry = lookup_secondary_tlb(guest_va, tag);
if (tlb2_entry != nullptr) {
tlb2_entry->flags |= TLBFlags::PTE_SET_C;
}
}
host_va = (uint8_t *)(tlb1_entry->host_va_offset + guest_va);
MemAccessType = true;
MemAddr = (uint64_t)host_va;
} else {
// primary TLB miss -> look up address in the secondary TLB
tlb2_entry = lookup_secondary_tlb(guest_va, tag);
if (tlb2_entry == nullptr) {
// secondary TLB miss ->
// perform full address translation and refill the secondary TLB
tlb2_entry = tlb2_refill(guest_va, 1);
}
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::DAR] = guest_va;
mmu_exception_handler(Except_Type::EXC_DSI, 0);
}
if (!(tlb2_entry->flags & TLBFlags::PTE_SET_C)) {
// perform full page address translation to update PTE.C bit
PATResult pat_res = page_address_translate(guest_va, false,
!!(ppc_state.msr & 0x4000), true);
tlb2_entry->flags |= TLBFlags::PTE_SET_C;
}
if (tlb2_entry->flags & TLBFlags::PAGE_MEM) { // is it a real memory region?
// refill the primary TLB
tlb1_entry->tag = tag;
tlb1_entry->flags = tlb2_entry->flags;
tlb1_entry->host_va_offset = tlb2_entry->host_va_offset;
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
tlb2_entry->reg_desc->devobj->write(tlb2_entry->reg_desc->start,
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;
}
}
// handle unaligned memory accesses
if (sizeof(T) > 1 && (guest_va & (sizeof(T) - 1))) {
write_unaligned(guest_va, host_va, value, sizeof(T));
return;
}
#if 1
// handle aligned memory accesses
switch(sizeof(T)) {
case 1:
*host_va = value;
break;
case 2:
WRITE_WORD_BE_A(host_va, value);
break;
case 4:
WRITE_DWORD_BE_A(host_va, value);
break;
case 8:
WRITE_QWORD_BE_A(host_va, value);
break;
}
#endif
}
// 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<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<uint64_t>(uint32_t guest_va, uint64_t value);
static uint32_t read_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t size) static uint32_t read_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t size)
{ {
uint32_t result = 0; uint32_t result = 0;
@ -1142,6 +1304,99 @@ static uint32_t read_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t siz
return result; return result;
} }
static void write_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t value,
uint32_t size)
{
// is it a misaligned cross-page write?
if (((guest_va & 0xFFF) + size) > 0x1000) {
Unaligned_crosspage = true;
// Break such a memory access into multiple, bytewise accesses.
// Because such accesses suffer a performance penalty, they will be
// presumably very rare so don't waste time optimizing the code below.
uint32_t shift = (size - 1) * 8;
for (int i = 0; i < size; shift -= 8, guest_va++, i++) {
mmu_write_vmem<uint8_t>(guest_va, (value >> shift) & 0xFF);
}
} else {
Unaligned_crosspage = false;
#if 1
switch(size) {
case 2:
WRITE_WORD_BE_U(host_va, value);
break;
case 4:
WRITE_DWORD_BE_U(host_va, value);
break;
case 8: // FIXME: should we raise alignment exception here?
WRITE_QWORD_BE_U(host_va, value);
break;
}
#endif
}
}
void mem_write_byte(uint32_t addr, uint8_t value) {
mmu_write_vmem<uint8_t>(addr, value);
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
write_phys_mem<uint8_t, true>(&last_write_area, addr, value);
}
void mem_write_word(uint32_t addr, uint16_t value) {
mmu_write_vmem<uint16_t>(addr, value);
if (addr & 1) {
mem_write_unaligned(addr, value, 2);
return;
}
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
write_phys_mem<uint16_t, true>(&last_write_area, addr, value);
}
void mem_write_dword(uint32_t addr, uint32_t value) {
mmu_write_vmem<uint32_t>(addr, value);
if (addr & 3) {
mem_write_unaligned(addr, value, 4);
return;
}
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
write_phys_mem<uint32_t, true>(&last_write_area, addr, value);
}
void mem_write_qword(uint32_t addr, uint64_t value) {
mmu_write_vmem<uint64_t>(addr, value);
if (addr & 7) {
LOG_F(ERROR, "SOS! Attempt to write unaligned QWORD to 0x%08X\n", addr);
exit(-1); // FIXME!
}
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
write_phys_mem<uint64_t, true>(&last_write_area, addr, value);
}
/** Grab a value from memory into a register */ /** Grab a value from memory into a register */
uint8_t mem_grab_byte(uint32_t addr) { uint8_t mem_grab_byte(uint32_t addr) {
tlb_translate_addr(addr); tlb_translate_addr(addr);

View File

@ -27,6 +27,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <array> #include <array>
#include <cinttypes> #include <cinttypes>
#include <vector> #include <vector>
#include "devices/memctrlbase.h"
/* Uncomment this to exhaustive MMU integrity checks. */ /* Uncomment this to exhaustive MMU integrity checks. */
//#define MMU_INTEGRITY_CHECKS //#define MMU_INTEGRITY_CHECKS
@ -53,6 +54,36 @@ typedef struct BATResult {
uint32_t phys; uint32_t phys;
} BATResult; } BATResult;
/** Result of the page address translation. */
typedef struct PATResult {
uint32_t phys;
uint8_t prot;
uint8_t pte_c_status; // status of the C bit of the PTE
} PATResult;
#define PAGE_SIZE_BITS 12
#define TLB_SIZE 4096
#define TLB2_WAYS 4
#define TLB_INVALID_TAG 0xFFFFFFFF
typedef struct TLBEntry {
uint32_t tag;
uint16_t flags;
uint16_t lru_bits;
union {
int64_t host_va_offset;
AddressMapEntry* reg_desc;
};
} TLBEntry;
enum TLBFlags : uint16_t {
PAGE_MEM = 1 << 0, // memory page backed by host memory
PAGE_IO = 1 << 1, // memory mapped I/O page
TLBE_FROM_BAT = 1 << 2, // TLB entry has been translated with BAT
TLBE_FROM_PAT = 1 << 3, // TLB entry has been translated with PAT
PAGE_WRITABLE = 1 << 4, // page is writable
PTE_SET_C = 1 << 5, // tells if C bit of the PTE needs to be updated
};
extern void ibat_update(uint32_t bat_reg); extern void ibat_update(uint32_t bat_reg);
extern void dbat_update(uint32_t bat_reg); extern void dbat_update(uint32_t bat_reg);
@ -60,7 +91,10 @@ extern void dbat_update(uint32_t bat_reg);
extern uint8_t* mmu_get_dma_mem(uint32_t addr, uint32_t size); 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 flush_tlb_entry(uint32_t ea); extern void mmu_pat_ctx_changed();
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);
@ -76,5 +110,7 @@ extern uint8_t* quickinstruction_translate(uint32_t address_grab);
template <class T> template <class T>
extern T mmu_read_vmem(uint32_t guest_va); extern T mmu_read_vmem(uint32_t guest_va);
template <class T>
extern void mmu_write_vmem(uint32_t guest_va, T value);
#endif // PPCMEMORY_H #endif // PPCMEMORY_H

View File

@ -26,12 +26,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <array> #include <array>
#include <cinttypes> #include <cinttypes>
#include <cstring> #include <cstring>
#include <functional>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <thirdparty/loguru/loguru.hpp> #include <thirdparty/loguru/loguru.hpp>
#include <thread> #include <thread>
#include <vector>
uint32_t crf_d; uint32_t crf_d;
uint32_t crf_s; uint32_t crf_s;
@ -188,6 +190,21 @@ inline void ppc_setsoov(uint32_t a, uint32_t b, uint32_t d) {
} }
} }
typedef std::function<void()> CtxSyncCallback;
std::vector<CtxSyncCallback> gCtxSyncCallbacks;
// perform context synchronization by executing registered actions if any
void do_ctx_sync() {
while (!gCtxSyncCallbacks.empty()) {
gCtxSyncCallbacks.back()();
gCtxSyncCallbacks.pop_back();
}
}
void add_ctx_sync_action(const CtxSyncCallback &cb) {
gCtxSyncCallbacks.push_back(cb);
}
/** /**
The core functionality of this PPC emulation is within all of these void functions. The core functionality of this PPC emulation is within all of these void functions.
This is where the opcode tables in the ppcemumain.h come into play - reducing the number of This is where the opcode tables in the ppcemumain.h come into play - reducing the number of
@ -768,6 +785,7 @@ void dppc_interpreter::ppc_mtsr() {
reg_s = (ppc_cur_instruction >> 21) & 31; reg_s = (ppc_cur_instruction >> 21) & 31;
grab_sr = (ppc_cur_instruction >> 16) & 15; grab_sr = (ppc_cur_instruction >> 16) & 15;
ppc_state.sr[grab_sr] = ppc_state.gpr[reg_s]; ppc_state.sr[grab_sr] = ppc_state.gpr[reg_s];
mmu_pat_ctx_changed();
} }
} }
@ -779,6 +797,7 @@ void dppc_interpreter::ppc_mtsrin() {
ppc_grab_regssb(); ppc_grab_regssb();
grab_sr = ppc_result_b >> 28; grab_sr = ppc_result_b >> 28;
ppc_state.sr[grab_sr] = ppc_result_d; ppc_state.sr[grab_sr] = ppc_result_d;
mmu_pat_ctx_changed();
} }
} }
@ -853,6 +872,11 @@ void dppc_interpreter::ppc_mtspr() {
ppc_state.spr[ref_spr] = ppc_state.gpr[reg_s]; ppc_state.spr[ref_spr] = ppc_state.gpr[reg_s];
} }
if (ref_spr == SPR::SDR1) {
LOG_F(INFO, "SDR1 changed to 0x%08X", ppc_state.spr[SPR::SDR1]);
mmu_pat_ctx_changed();
}
switch (ref_spr) { switch (ref_spr) {
// Mirror the TBRs in the SPR range to the user-mode TBRs. // Mirror the TBRs in the SPR range to the user-mode TBRs.
case 284: case 284:
@ -1320,7 +1344,7 @@ void dppc_interpreter::ppc_eieio() {
} }
void dppc_interpreter::ppc_isync() { void dppc_interpreter::ppc_isync() {
/* placeholder */ do_ctx_sync();
} }
void dppc_interpreter::ppc_sync() { void dppc_interpreter::ppc_sync() {
@ -1362,10 +1386,10 @@ void dppc_interpreter::ppc_dcbz() {
ppc_effective_address &= 0xFFFFFFE0; // align EA on a 32-byte boundary ppc_effective_address &= 0xFFFFFFE0; // align EA on a 32-byte boundary
mem_write_qword(ppc_effective_address, 0); //mem_write_qword(ppc_effective_address, 0);
mem_write_qword((ppc_effective_address + 8), 0); //mem_write_qword((ppc_effective_address + 8), 0);
mem_write_qword((ppc_effective_address + 16), 0); //mem_write_qword((ppc_effective_address + 16), 0);
mem_write_qword((ppc_effective_address + 24), 0); //mem_write_qword((ppc_effective_address + 24), 0);
} }
@ -1378,7 +1402,8 @@ void dppc_interpreter::ppc_stb() {
ppc_grab_regssa(); ppc_grab_regssa();
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += reg_a ? ppc_result_a : 0; ppc_effective_address += reg_a ? ppc_result_a : 0;
mem_write_byte(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint8_t>(ppc_effective_address, ppc_result_d);
//mem_write_byte(ppc_effective_address, ppc_result_d);
} }
void dppc_interpreter::ppc_stbx() { void dppc_interpreter::ppc_stbx() {
@ -1387,7 +1412,8 @@ void dppc_interpreter::ppc_stbx() {
#endif #endif
ppc_grab_regssab(); ppc_grab_regssab();
ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b;
mem_write_byte(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint8_t>(ppc_effective_address, ppc_result_d);
//mem_write_byte(ppc_effective_address, ppc_result_d);
} }
void dppc_interpreter::ppc_stbu() { void dppc_interpreter::ppc_stbu() {
@ -1398,7 +1424,8 @@ void dppc_interpreter::ppc_stbu() {
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += ppc_result_a; ppc_effective_address += ppc_result_a;
mem_write_byte(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint8_t>(ppc_effective_address, ppc_result_d);
//mem_write_byte(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -1412,7 +1439,8 @@ void dppc_interpreter::ppc_stbux() {
ppc_grab_regssab(); ppc_grab_regssab();
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = ppc_result_a + ppc_result_b; ppc_effective_address = ppc_result_a + ppc_result_b;
mem_write_byte(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint8_t>(ppc_effective_address, ppc_result_d);
//mem_write_byte(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -1426,7 +1454,8 @@ void dppc_interpreter::ppc_sth() {
ppc_grab_regssa(); ppc_grab_regssa();
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0; ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
mem_write_word(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint16_t>(ppc_effective_address, ppc_result_d);
//mem_write_word(ppc_effective_address, ppc_result_d);
} }
void dppc_interpreter::ppc_sthu() { void dppc_interpreter::ppc_sthu() {
@ -1437,7 +1466,8 @@ void dppc_interpreter::ppc_sthu() {
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += ppc_result_a; ppc_effective_address += ppc_result_a;
mem_write_word(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint16_t>(ppc_effective_address, ppc_result_d);
//mem_write_word(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -1451,7 +1481,8 @@ void dppc_interpreter::ppc_sthux() {
ppc_grab_regssab(); ppc_grab_regssab();
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = ppc_result_a + ppc_result_b; ppc_effective_address = ppc_result_a + ppc_result_b;
mem_write_word(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint16_t>(ppc_effective_address, ppc_result_d);
//mem_write_word(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -1464,7 +1495,8 @@ void dppc_interpreter::ppc_sthx() {
#endif #endif
ppc_grab_regssab(); ppc_grab_regssab();
ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b;
mem_write_word(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint16_t>(ppc_effective_address, ppc_result_d);
//mem_write_word(ppc_effective_address, ppc_result_d);
} }
void dppc_interpreter::ppc_sthbrx() { void dppc_interpreter::ppc_sthbrx() {
@ -1474,8 +1506,10 @@ void dppc_interpreter::ppc_sthbrx() {
ppc_grab_regssab(); ppc_grab_regssab();
ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b); ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b);
ppc_result_d = (uint32_t)(BYTESWAP_16((uint16_t)ppc_result_d)); ppc_result_d = (uint32_t)(BYTESWAP_16((uint16_t)ppc_result_d));
mem_write_word(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint16_t>(ppc_effective_address, ppc_result_d);
//mem_write_word(ppc_effective_address, ppc_result_d);
} }
void dppc_interpreter::ppc_stw() { void dppc_interpreter::ppc_stw() {
#ifdef CPU_PROFILING #ifdef CPU_PROFILING
num_int_stores++; num_int_stores++;
@ -1483,7 +1517,8 @@ void dppc_interpreter::ppc_stw() {
ppc_grab_regssa(); ppc_grab_regssa();
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += reg_a ? ppc_result_a : 0; ppc_effective_address += reg_a ? ppc_result_a : 0;
mem_write_dword(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_result_d);
//mem_write_dword(ppc_effective_address, ppc_result_d);
} }
void dppc_interpreter::ppc_stwx() { void dppc_interpreter::ppc_stwx() {
@ -1492,7 +1527,8 @@ void dppc_interpreter::ppc_stwx() {
#endif #endif
ppc_grab_regssab(); ppc_grab_regssab();
ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b;
mem_write_dword(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_result_d);
//mem_write_dword(ppc_effective_address, ppc_result_d);
} }
void dppc_interpreter::ppc_stwcx() { void dppc_interpreter::ppc_stwcx() {
@ -1506,7 +1542,8 @@ void dppc_interpreter::ppc_stwcx() {
ppc_grab_regssab(); ppc_grab_regssab();
ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b); ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b);
if (ppc_state.reserve) { if (ppc_state.reserve) {
mem_write_dword(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_result_d);
//mem_write_dword(ppc_effective_address, ppc_result_d);
ppc_state.cr |= (ppc_state.spr[SPR::XER] & 0x80000000) ? 0x30000000 : 0x20000000; ppc_state.cr |= (ppc_state.spr[SPR::XER] & 0x80000000) ? 0x30000000 : 0x20000000;
ppc_state.reserve = false; ppc_state.reserve = false;
} else { } else {
@ -1523,7 +1560,8 @@ void dppc_interpreter::ppc_stwu() {
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += ppc_result_a; ppc_effective_address += ppc_result_a;
mem_write_dword(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_result_d);
//mem_write_dword(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -1537,7 +1575,8 @@ void dppc_interpreter::ppc_stwux() {
ppc_grab_regssab(); ppc_grab_regssab();
if (reg_a != 0) { if (reg_a != 0) {
ppc_effective_address = ppc_result_a + ppc_result_b; ppc_effective_address = ppc_result_a + ppc_result_b;
mem_write_dword(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_result_d);
//mem_write_dword(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address; ppc_state.gpr[reg_a] = ppc_effective_address;
} else { } else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
@ -1551,7 +1590,8 @@ void dppc_interpreter::ppc_stwbrx() {
ppc_grab_regssab(); ppc_grab_regssab();
ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b;
ppc_result_d = BYTESWAP_32(ppc_result_d); ppc_result_d = BYTESWAP_32(ppc_result_d);
mem_write_dword(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_result_d);
//mem_write_dword(ppc_effective_address, ppc_result_d);
} }
void dppc_interpreter::ppc_stmw() { void dppc_interpreter::ppc_stmw() {
@ -1568,7 +1608,8 @@ void dppc_interpreter::ppc_stmw() {
} }
for (; reg_s <= 31; reg_s++) { for (; reg_s <= 31; reg_s++) {
mem_write_dword(ppc_effective_address, ppc_state.gpr[reg_s]); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_state.gpr[reg_s]);
//mem_write_dword(ppc_effective_address, ppc_state.gpr[reg_s]);
ppc_effective_address += 4; ppc_effective_address += 4;
} }
} }
@ -1886,20 +1927,26 @@ void dppc_interpreter::ppc_lswi() {
while (grab_inb > 0) { while (grab_inb > 0) {
switch (grab_inb) { switch (grab_inb) {
case 1: case 1:
stringed_word = mem_grab_byte(ppc_effective_address) << 24; stringed_word = mmu_read_vmem<uint8_t>(ppc_effective_address) << 24;
//stringed_word = mem_grab_byte(ppc_effective_address) << 24;
ppc_state.gpr[reg_d] = stringed_word; ppc_state.gpr[reg_d] = stringed_word;
grab_inb = 0; grab_inb = 0;
break; break;
case 2: case 2:
stringed_word = mem_grab_byte(ppc_effective_address) << 24; stringed_word = mmu_read_vmem<uint8_t>(ppc_effective_address) << 24;
stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; //stringed_word = mem_grab_byte(ppc_effective_address) << 24;
stringed_word += mmu_read_vmem<uint8_t>(ppc_effective_address + 1) << 16;
//stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16;
ppc_state.gpr[reg_d] = stringed_word; ppc_state.gpr[reg_d] = stringed_word;
grab_inb = 0; grab_inb = 0;
break; break;
case 3: case 3:
stringed_word = mem_grab_byte(ppc_effective_address) << 24; stringed_word = mmu_read_vmem<uint8_t>(ppc_effective_address) << 24;
stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; //stringed_word = mem_grab_byte(ppc_effective_address) << 24;
stringed_word += mem_grab_byte(ppc_effective_address + 2) << 8; stringed_word += mmu_read_vmem<uint8_t>(ppc_effective_address + 1) << 16;
//stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16;
stringed_word += mmu_read_vmem<uint8_t>(ppc_effective_address + 2) << 8;
//stringed_word += mem_grab_byte(ppc_effective_address + 2) << 8;
ppc_state.gpr[reg_d] = stringed_word; ppc_state.gpr[reg_d] = stringed_word;
grab_inb = 0; grab_inb = 0;
break; break;
@ -1934,20 +1981,26 @@ void dppc_interpreter::ppc_lswx() {
while (grab_inb > 0) { while (grab_inb > 0) {
switch (grab_inb) { switch (grab_inb) {
case 1: case 1:
stringed_word = mem_grab_byte(ppc_effective_address) << 24; stringed_word = mmu_read_vmem<uint8_t>(ppc_effective_address) << 24;
//stringed_word = mem_grab_byte(ppc_effective_address) << 24;
ppc_state.gpr[reg_d] = stringed_word; ppc_state.gpr[reg_d] = stringed_word;
grab_inb = 0; grab_inb = 0;
break; break;
case 2: case 2:
stringed_word = mem_grab_byte(ppc_effective_address) << 24; stringed_word = mmu_read_vmem<uint8_t>(ppc_effective_address) << 24;
stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; //stringed_word = mem_grab_byte(ppc_effective_address) << 24;
stringed_word += mmu_read_vmem<uint8_t>(ppc_effective_address + 1) << 16;
//stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16;
ppc_state.gpr[reg_d] = stringed_word; ppc_state.gpr[reg_d] = stringed_word;
grab_inb = 0; grab_inb = 0;
break; break;
case 3: case 3:
stringed_word = mem_grab_byte(ppc_effective_address) << 24; stringed_word = mmu_read_vmem<uint8_t>(ppc_effective_address) << 24;
stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; //stringed_word = mem_grab_byte(ppc_effective_address) << 24;
stringed_word += mem_grab_byte(ppc_effective_address + 2) << 8; stringed_word += mmu_read_vmem<uint8_t>(ppc_effective_address + 1) << 16;
//stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16;
stringed_word += mmu_read_vmem<uint8_t>(ppc_effective_address + 2) << 8;
//stringed_word += mem_grab_byte(ppc_effective_address + 2) << 8;
ppc_state.gpr[reg_d] = stringed_word; ppc_state.gpr[reg_d] = stringed_word;
grab_inb = 0; grab_inb = 0;
break; break;
@ -1973,22 +2026,29 @@ void dppc_interpreter::ppc_stswi() {
while (grab_inb > 0) { while (grab_inb > 0) {
switch (grab_inb) { switch (grab_inb) {
case 1: case 1:
mem_write_byte(ppc_effective_address, (ppc_result_d >> 24)); mmu_write_vmem<uint8_t>(ppc_effective_address, (ppc_result_d >> 24));
//mem_write_byte(ppc_effective_address, (ppc_result_d >> 24));
grab_inb = 0; grab_inb = 0;
break; break;
case 2: case 2:
mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); mmu_write_vmem<uint8_t>(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF));
mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); //mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF));
mmu_write_vmem<uint8_t>((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF));
//mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF));
grab_inb = 0; grab_inb = 0;
break; break;
case 3: case 3:
mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); mmu_write_vmem<uint8_t>(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF));
mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); //mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF));
mem_write_byte((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF)); mmu_write_vmem<uint8_t>((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF));
//mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF));
mmu_write_vmem<uint8_t>((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF));
//mem_write_byte((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF));
grab_inb = 0; grab_inb = 0;
break; break;
default: default:
mem_write_dword(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_result_d);
//mem_write_dword(ppc_effective_address, ppc_result_d);
reg_s++; reg_s++;
ppc_effective_address += 4; ppc_effective_address += 4;
grab_inb -= 4; grab_inb -= 4;
@ -2007,22 +2067,29 @@ void dppc_interpreter::ppc_stswx() {
while (grab_inb > 0) { while (grab_inb > 0) {
switch (grab_inb) { switch (grab_inb) {
case 1: case 1:
mem_write_byte(ppc_effective_address, (ppc_result_d >> 24)); mmu_write_vmem<uint8_t>(ppc_effective_address, (ppc_result_d >> 24));
//mem_write_byte(ppc_effective_address, (ppc_result_d >> 24));
grab_inb = 0; grab_inb = 0;
break; break;
case 2: case 2:
mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); mmu_write_vmem<uint8_t>(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF));
mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); //mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF));
mmu_write_vmem<uint8_t>((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF));
//mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF));
grab_inb = 0; grab_inb = 0;
break; break;
case 3: case 3:
mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); mmu_write_vmem<uint8_t>(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF));
mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); //mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF));
mem_write_byte((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF)); mmu_write_vmem<uint8_t>((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF));
//mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF));
mmu_write_vmem<uint8_t>((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF));
//mem_write_byte((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF));
grab_inb = 0; grab_inb = 0;
break; break;
default: default:
mem_write_dword(ppc_effective_address, ppc_result_d); mmu_write_vmem<uint32_t>(ppc_effective_address, ppc_result_d);
//mem_write_dword(ppc_effective_address, ppc_result_d);
reg_s++; reg_s++;
ppc_effective_address += 4; ppc_effective_address += 4;
grab_inb -= 4; grab_inb -= 4;
@ -2037,7 +2104,7 @@ void dppc_interpreter::ppc_tlbie() {
num_supervisor_instrs++; num_supervisor_instrs++;
#endif #endif
flush_tlb_entry(ppc_state.gpr[(ppc_cur_instruction >> 11) & 31]); tlb_flush_entry(ppc_state.gpr[(ppc_cur_instruction >> 11) & 31]);
} }
void dppc_interpreter::ppc_tlbia() { void dppc_interpreter::ppc_tlbia() {

View File

@ -118,8 +118,10 @@ int main(int argc, char** argv) {
loguru::init(argc, argv); loguru::init(argc, argv);
loguru::add_file("dingusppc.log", loguru::Append, 0); loguru::add_file("dingusppc.log", loguru::Append, 0);
} else { } else {
loguru::g_stderr_verbosity = 0; loguru::g_preamble_uptime = false;
loguru::g_stderr_verbosity = loguru::Verbosity_INFO;
loguru::init(argc, argv); loguru::init(argc, argv);
loguru::add_file("exceptions.log", loguru::Truncate, -7);
} }
if (*machine_opt) { if (*machine_opt) {