From 089645e830746580e39fb45f607bf4ccc7223604 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Tue, 3 Aug 2021 16:01:32 +0200 Subject: [PATCH] Implement SoftTLB for writes. --- cpu/ppc/poweropcodes.cpp | 14 +- cpu/ppc/ppcemu.h | 4 + cpu/ppc/ppcfpopcodes.cpp | 51 +++-- cpu/ppc/ppcmmu.cpp | 437 +++++++++++++++++++++++++++++++-------- cpu/ppc/ppcmmu.h | 38 +++- cpu/ppc/ppcopcodes.cpp | 163 ++++++++++----- main.cpp | 4 +- 7 files changed, 546 insertions(+), 165 deletions(-) diff --git a/cpu/ppc/poweropcodes.cpp b/cpu/ppc/poweropcodes.cpp index 6e2b3c1..3ce0e2c 100644 --- a/cpu/ppc/poweropcodes.cpp +++ b/cpu/ppc/poweropcodes.cpp @@ -148,22 +148,26 @@ void dppc_interpreter::power_lscbx() { if (match_found == false) { switch (shift_amount) { case 0: - return_value = mem_grab_byte(ppc_effective_address); + return_value = mmu_read_vmem(ppc_effective_address); + //return_value = mem_grab_byte(ppc_effective_address); ppc_result_d = (ppc_result_d & 0x00FFFFFF) | (return_value << 24); ppc_store_result_regd(); break; case 1: - return_value = mem_grab_byte(ppc_effective_address); + return_value = mmu_read_vmem(ppc_effective_address); + //return_value = mem_grab_byte(ppc_effective_address); ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16); ppc_store_result_regd(); break; case 2: - return_value = mem_grab_byte(ppc_effective_address); + return_value = mmu_read_vmem(ppc_effective_address); + //return_value = mem_grab_byte(ppc_effective_address); ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8); ppc_store_result_regd(); break; case 3: - return_value = mem_grab_byte(ppc_effective_address); + return_value = mmu_read_vmem(ppc_effective_address); + //return_value = mem_grab_byte(ppc_effective_address); ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value; ppc_store_result_regd(); break; @@ -494,4 +498,4 @@ void dppc_interpreter::power_srlq() { void dppc_interpreter::power_srq() { LOG_F(WARNING, "OOPS! Placeholder for srq!!! \n"); -} \ No newline at end of file +} diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index d396fb2..903f911 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -25,6 +25,7 @@ along with this program. If not, see . #include "devices/memctrlbase.h" #include "endianswap.h" #include +#include #include #include @@ -301,6 +302,9 @@ void ppc_fp_changecrf1(); // MEMORY DECLARATIONS extern MemCtrlBase* mem_ctrl_instance; +//typedef std::function CtxSyncCallback; +extern void add_ctx_sync_action(const std::function &); + // The functions used by the PowerPC processor namespace dppc_interpreter { extern void ppc_bcctr(); diff --git a/cpu/ppc/ppcfpopcodes.cpp b/cpu/ppc/ppcfpopcodes.cpp index e3078bf..b4d6d43 100644 --- a/cpu/ppc/ppcfpopcodes.cpp +++ b/cpu/ppc/ppcfpopcodes.cpp @@ -674,11 +674,11 @@ void dppc_interpreter::ppc_fctiw() { if (std::isnan(val_reg_b)) { ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpscr |= 0x1000100; - } + } else if (val_reg_b > static_cast(0x7fffffff)) { ppc_state.fpr[reg_d].int64_r = 0x7fffffff; ppc_state.fpscr |= 0x100; - } + } else if (val_reg_b < -static_cast(0x80000000)) { ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpscr |= 0x100; @@ -696,7 +696,7 @@ void dppc_interpreter::ppc_fctiw() { } ppc_store_dfpresult_int(reg_d); - + } if (rc_flag) @@ -710,15 +710,15 @@ void dppc_interpreter::ppc_fctiwz() { if (std::isnan(val_reg_b)) { ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpscr |= 0x1000100; - } + } else if (val_reg_b > static_cast(0x7fffffff)) { ppc_state.fpr[reg_d].int64_r = 0x7fffffff; ppc_state.fpscr |= 0x100; - } + } else if (val_reg_b < -static_cast(0x80000000)) { ppc_state.fpr[reg_d].int64_r = 0x80000000; ppc_state.fpscr |= 0x100; - } + } else { ppc_result64_d = round_to_zero(val_reg_b); @@ -735,7 +735,8 @@ void dppc_interpreter::ppc_lfs() { ppc_grab_regsfpdia(); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += (reg_a) ? val_reg_a : 0; - ppc_result64_d = mem_grab_dword(ppc_effective_address); + ppc_result64_d = mmu_read_vmem(ppc_effective_address); + //ppc_result64_d = mem_grab_dword(ppc_effective_address); ppc_store_sfpresult_int(reg_d); } @@ -745,7 +746,8 @@ void dppc_interpreter::ppc_lfsu() { if (reg_a) { ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += (reg_a) ? val_reg_a : 0; - ppc_result64_d = mem_grab_dword(ppc_effective_address); + ppc_result64_d = mmu_read_vmem(ppc_effective_address); + //ppc_result64_d = mem_grab_dword(ppc_effective_address); ppc_store_sfpresult_int(reg_d); ppc_state.gpr[reg_a] = ppc_effective_address; } else { @@ -756,7 +758,8 @@ void dppc_interpreter::ppc_lfsu() { void dppc_interpreter::ppc_lfsx() { ppc_grab_regsfpdiab(); 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(ppc_effective_address); + //ppc_result64_d = mem_grab_dword(ppc_effective_address); ppc_store_sfpresult_int(reg_d); } @@ -764,7 +767,8 @@ void dppc_interpreter::ppc_lfsux() { ppc_grab_regsfpdiab(); if (reg_a) { ppc_effective_address = val_reg_a + val_reg_b; - ppc_result64_d = mem_grab_dword(ppc_effective_address); + ppc_result64_d = mmu_read_vmem(ppc_effective_address); + //ppc_result64_d = mem_grab_dword(ppc_effective_address); ppc_store_sfpresult_int(reg_d); ppc_state.gpr[reg_a] = ppc_effective_address; } else { @@ -820,7 +824,8 @@ void dppc_interpreter::ppc_stfs() { ppc_grab_regsfpsia(); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); 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(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() { @@ -828,7 +833,8 @@ void dppc_interpreter::ppc_stfsu() { if (reg_a != 0) { ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += val_reg_a; - mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r)); + mmu_write_vmem(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; } else { 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() { ppc_grab_regsfpsiab(); 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(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() { ppc_grab_regsfpsiab(); if (reg_a) { 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(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; } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); @@ -856,7 +864,8 @@ void dppc_interpreter::ppc_stfd() { ppc_grab_regsfpsia(); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); 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(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() { @@ -864,7 +873,8 @@ void dppc_interpreter::ppc_stfdu() { if (reg_a != 0) { ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += val_reg_a; - mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r); + mmu_write_vmem(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; } else { 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() { ppc_grab_regsfpsiab(); 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(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() { ppc_grab_regsfpsiab(); if (reg_a != 0) { 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(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; } else { 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() { ppc_grab_regsfpsiab(); 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(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 diff --git a/cpu/ppc/ppcmmu.cpp b/cpu/ppc/ppcmmu.cpp index f9f8755..12d656f 100644 --- a/cpu/ppc/ppcmmu.cpp +++ b/cpu/ppc/ppcmmu.cpp @@ -137,6 +137,7 @@ public: /** 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; @@ -239,6 +240,21 @@ static inline void write_phys_mem(AddressMapEntry *mru_rgn, uint32_t addr, T val #ifdef MMU_PROFILING dmem_writes_total++; #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)) { case 1: *(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 iomem_writes_total++; #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, sizeof(T)); } else { @@ -298,6 +326,9 @@ void ppc_set_cur_instruction(const uint8_t* ptr) { ppc_cur_instruction = READ_DWORD_BE_A(ptr); } +bool gTLBFlushBatEntries = false; +bool gTLBFlushPatEntries = false; + void ibat_update(uint32_t bat_reg) { int upper_reg_num; uint32_t bl, hi_mask; @@ -335,6 +366,19 @@ void dbat_update(uint32_t bat_reg) { bat_entry->hi_mask = 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; + + 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; } -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; unsigned key, pp; 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; } - /* return physical address */ - return ((pte_word2 & 0xFFFFF000) | (la & 0x00000FFF)); + /* return physical address, access protection and C status */ + return PATResult{ + ((pte_word2 & 0xFFFFF000) | (la & 0x00000FFF)), + static_cast((key << 2) | pp), + static_cast(pte_word2 & 0x80) + }; } /** PowerPC-style MMU instruction address translation. */ @@ -535,7 +585,8 @@ static uint32_t ppc_mmu_instr_translate(uint32_t la) { /* page address translation */ 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 ptab_transl_total++; @@ -581,7 +632,8 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write) { /* page address translation */ 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 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(&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(&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(&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(&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 static std::array mode1_tlb1; static std::array mode2_tlb1; @@ -721,13 +706,13 @@ uint32_t tlb_size_mask = TLB_SIZE - 1; uint64_t UnmappedVal = -1ULL; TLBEntry UnmappedMem = {TLB_INVALID_TAG, 0, 0, 0}; -uint8_t MMUMode = {0xFF}; +uint8_t CurMMUMode = {0xFF}; // current MMU mode void mmu_change_mode() { 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) { case 0: // real address mode pCurTLB1 = &mode1_tlb1[0]; @@ -742,7 +727,7 @@ void mmu_change_mode() pCurTLB2 = &mode3_tlb2[0]; 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) { uint32_t phys_addr; + uint16_t flags = 0; TLBEntry *tlb_entry; 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) { // check block protection 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::DAR] = guest_va; mmu_exception_handler(Except_Type::EXC_DSI, 0); } 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 { // page address translation - phys_addr = page_address_translate(guest_va, false, - !!(ppc_state.msr & 0x4000), is_write); + PATResult pat_res = page_address_translate(guest_va, false, + !!(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; + 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 @@ -848,11 +856,11 @@ static TLBEntry* tlb2_refill(uint32_t guest_va, int is_write) // refill the secondary TLB tlb_entry = tlb2_target_entry(tag); tlb_entry->tag = tag; - if (reg_desc->type & RT_MMIO) { - tlb_entry->flags = 2; // MMIO region + if (reg_desc->type & RT_MMIO) { // MMIO region + tlb_entry->flags = flags | TLBFlags::PAGE_IO; tlb_entry->reg_desc = reg_desc; - } else { - tlb_entry->flags = 1; // memory region backed by host memory + } else { // 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 + (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; @@ -878,12 +886,12 @@ void flush_tlb_entry(uint32_t ea) tlb2 = &mode1_tlb2[0]; break; case 1: - tlb1 = &mode1_tlb1[0]; - tlb2 = &mode1_tlb2[0]; + tlb1 = &mode2_tlb1[0]; + tlb2 = &mode2_tlb2[0]; break; case 2: - tlb1 = &mode1_tlb1[0]; - tlb2 = &mode1_tlb2[0]; + tlb1 = &mode3_tlb1[0]; + tlb2 = &mode3_tlb2[0]; 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) { 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); } - 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 tlb1_entry->tag = tag; - tlb1_entry->flags = 1; + tlb1_entry->flags = tlb2_entry->flags; tlb1_entry->host_va_offset = tlb2_entry->host_va_offset; MemAccessType = true; 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; } +// Forward declarations. 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 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); } - 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 tlb1_entry->tag = tag; - tlb1_entry->flags = 1; + 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); } else { // otherwise, it's an access to a memory-mapped device @@ -1117,6 +1175,110 @@ template uint16_t mmu_read_vmem(uint32_t guest_va); template uint32_t mmu_read_vmem(uint32_t guest_va); template uint64_t mmu_read_vmem(uint32_t guest_va); +template +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(uint32_t guest_va, uint8_t value); +template void mmu_write_vmem(uint32_t guest_va, uint16_t value); +template void mmu_write_vmem(uint32_t guest_va, uint32_t value); +template void mmu_write_vmem(uint32_t guest_va, uint64_t value); + static uint32_t read_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t size) { 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; } +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(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(addr, value); + + /* data address translation if enabled */ + if (ppc_state.msr & 0x10) { + addr = ppc_mmu_addr_translate(addr, 1); + } + + write_phys_mem(&last_write_area, addr, value); +} + +void mem_write_word(uint32_t addr, uint16_t value) { + mmu_write_vmem(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(&last_write_area, addr, value); +} + +void mem_write_dword(uint32_t addr, uint32_t value) { + mmu_write_vmem(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(&last_write_area, addr, value); +} + +void mem_write_qword(uint32_t addr, uint64_t value) { + mmu_write_vmem(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(&last_write_area, addr, value); +} + /** Grab a value from memory into a register */ uint8_t mem_grab_byte(uint32_t addr) { tlb_translate_addr(addr); diff --git a/cpu/ppc/ppcmmu.h b/cpu/ppc/ppcmmu.h index c05cc89..80ae209 100644 --- a/cpu/ppc/ppcmmu.h +++ b/cpu/ppc/ppcmmu.h @@ -27,6 +27,7 @@ along with this program. If not, see . #include #include #include +#include "devices/memctrlbase.h" /* Uncomment this to exhaustive MMU integrity checks. */ //#define MMU_INTEGRITY_CHECKS @@ -53,6 +54,36 @@ typedef struct BATResult { uint32_t phys; } 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 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 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 mem_write_byte(uint32_t addr, uint8_t value); @@ -76,5 +110,7 @@ extern uint8_t* quickinstruction_translate(uint32_t address_grab); template extern T mmu_read_vmem(uint32_t guest_va); +template +extern void mmu_write_vmem(uint32_t guest_va, T value); #endif // PPCMEMORY_H diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index 1bf96c0..71e8572 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -26,12 +26,14 @@ along with this program. If not, see . #include #include #include +#include #include #include #include #include #include #include +#include uint32_t crf_d; uint32_t crf_s; @@ -188,6 +190,21 @@ inline void ppc_setsoov(uint32_t a, uint32_t b, uint32_t d) { } } +typedef std::function CtxSyncCallback; +std::vector 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. 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; grab_sr = (ppc_cur_instruction >> 16) & 15; 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(); grab_sr = ppc_result_b >> 28; 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]; } + 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) { // Mirror the TBRs in the SPR range to the user-mode TBRs. case 284: @@ -1320,7 +1344,7 @@ void dppc_interpreter::ppc_eieio() { } void dppc_interpreter::ppc_isync() { - /* placeholder */ + do_ctx_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 - mem_write_qword(ppc_effective_address, 0); - mem_write_qword((ppc_effective_address + 8), 0); - mem_write_qword((ppc_effective_address + 16), 0); - mem_write_qword((ppc_effective_address + 24), 0); + //mem_write_qword(ppc_effective_address, 0); + //mem_write_qword((ppc_effective_address + 8), 0); + //mem_write_qword((ppc_effective_address + 16), 0); + //mem_write_qword((ppc_effective_address + 24), 0); } @@ -1378,7 +1402,8 @@ void dppc_interpreter::ppc_stb() { ppc_grab_regssa(); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += reg_a ? ppc_result_a : 0; - mem_write_byte(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_byte(ppc_effective_address, ppc_result_d); } void dppc_interpreter::ppc_stbx() { @@ -1387,7 +1412,8 @@ void dppc_interpreter::ppc_stbx() { #endif ppc_grab_regssab(); 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(ppc_effective_address, ppc_result_d); + //mem_write_byte(ppc_effective_address, ppc_result_d); } void dppc_interpreter::ppc_stbu() { @@ -1398,7 +1424,8 @@ void dppc_interpreter::ppc_stbu() { if (reg_a != 0) { ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += ppc_result_a; - mem_write_byte(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_byte(ppc_effective_address, ppc_result_d); ppc_state.gpr[reg_a] = ppc_effective_address; } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); @@ -1412,7 +1439,8 @@ void dppc_interpreter::ppc_stbux() { ppc_grab_regssab(); if (reg_a != 0) { ppc_effective_address = ppc_result_a + ppc_result_b; - mem_write_byte(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_byte(ppc_effective_address, ppc_result_d); ppc_state.gpr[reg_a] = ppc_effective_address; } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); @@ -1426,7 +1454,8 @@ void dppc_interpreter::ppc_sth() { ppc_grab_regssa(); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0; - mem_write_word(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_word(ppc_effective_address, ppc_result_d); } void dppc_interpreter::ppc_sthu() { @@ -1437,7 +1466,8 @@ void dppc_interpreter::ppc_sthu() { if (reg_a != 0) { ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += ppc_result_a; - mem_write_word(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_word(ppc_effective_address, ppc_result_d); ppc_state.gpr[reg_a] = ppc_effective_address; } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); @@ -1451,7 +1481,8 @@ void dppc_interpreter::ppc_sthux() { ppc_grab_regssab(); if (reg_a != 0) { ppc_effective_address = ppc_result_a + ppc_result_b; - mem_write_word(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_word(ppc_effective_address, ppc_result_d); ppc_state.gpr[reg_a] = ppc_effective_address; } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); @@ -1464,7 +1495,8 @@ void dppc_interpreter::ppc_sthx() { #endif ppc_grab_regssab(); 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(ppc_effective_address, ppc_result_d); + //mem_write_word(ppc_effective_address, ppc_result_d); } void dppc_interpreter::ppc_sthbrx() { @@ -1474,8 +1506,10 @@ void dppc_interpreter::ppc_sthbrx() { ppc_grab_regssab(); 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)); - mem_write_word(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_word(ppc_effective_address, ppc_result_d); } + void dppc_interpreter::ppc_stw() { #ifdef CPU_PROFILING num_int_stores++; @@ -1483,7 +1517,8 @@ void dppc_interpreter::ppc_stw() { ppc_grab_regssa(); ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += reg_a ? ppc_result_a : 0; - mem_write_dword(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_dword(ppc_effective_address, ppc_result_d); } void dppc_interpreter::ppc_stwx() { @@ -1492,7 +1527,8 @@ void dppc_interpreter::ppc_stwx() { #endif ppc_grab_regssab(); 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(ppc_effective_address, ppc_result_d); + //mem_write_dword(ppc_effective_address, ppc_result_d); } void dppc_interpreter::ppc_stwcx() { @@ -1506,7 +1542,8 @@ void dppc_interpreter::ppc_stwcx() { ppc_grab_regssab(); ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b); if (ppc_state.reserve) { - mem_write_dword(ppc_effective_address, ppc_result_d); + mmu_write_vmem(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.reserve = false; } else { @@ -1523,7 +1560,8 @@ void dppc_interpreter::ppc_stwu() { if (reg_a != 0) { ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); ppc_effective_address += ppc_result_a; - mem_write_dword(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_dword(ppc_effective_address, ppc_result_d); ppc_state.gpr[reg_a] = ppc_effective_address; } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); @@ -1537,7 +1575,8 @@ void dppc_interpreter::ppc_stwux() { ppc_grab_regssab(); if (reg_a != 0) { ppc_effective_address = ppc_result_a + ppc_result_b; - mem_write_dword(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_dword(ppc_effective_address, ppc_result_d); ppc_state.gpr[reg_a] = ppc_effective_address; } else { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); @@ -1551,7 +1590,8 @@ void dppc_interpreter::ppc_stwbrx() { ppc_grab_regssab(); ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; ppc_result_d = BYTESWAP_32(ppc_result_d); - mem_write_dword(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_dword(ppc_effective_address, ppc_result_d); } void dppc_interpreter::ppc_stmw() { @@ -1568,7 +1608,8 @@ void dppc_interpreter::ppc_stmw() { } for (; reg_s <= 31; reg_s++) { - mem_write_dword(ppc_effective_address, ppc_state.gpr[reg_s]); + mmu_write_vmem(ppc_effective_address, ppc_state.gpr[reg_s]); + //mem_write_dword(ppc_effective_address, ppc_state.gpr[reg_s]); ppc_effective_address += 4; } } @@ -1886,20 +1927,26 @@ void dppc_interpreter::ppc_lswi() { while (grab_inb > 0) { switch (grab_inb) { case 1: - stringed_word = mem_grab_byte(ppc_effective_address) << 24; + stringed_word = mmu_read_vmem(ppc_effective_address) << 24; + //stringed_word = mem_grab_byte(ppc_effective_address) << 24; ppc_state.gpr[reg_d] = stringed_word; grab_inb = 0; break; case 2: - stringed_word = mem_grab_byte(ppc_effective_address) << 24; - stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; + stringed_word = mmu_read_vmem(ppc_effective_address) << 24; + //stringed_word = mem_grab_byte(ppc_effective_address) << 24; + stringed_word += mmu_read_vmem(ppc_effective_address + 1) << 16; + //stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; ppc_state.gpr[reg_d] = stringed_word; grab_inb = 0; break; case 3: - stringed_word = mem_grab_byte(ppc_effective_address) << 24; - stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; - stringed_word += mem_grab_byte(ppc_effective_address + 2) << 8; + stringed_word = mmu_read_vmem(ppc_effective_address) << 24; + //stringed_word = mem_grab_byte(ppc_effective_address) << 24; + stringed_word += mmu_read_vmem(ppc_effective_address + 1) << 16; + //stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; + stringed_word += mmu_read_vmem(ppc_effective_address + 2) << 8; + //stringed_word += mem_grab_byte(ppc_effective_address + 2) << 8; ppc_state.gpr[reg_d] = stringed_word; grab_inb = 0; break; @@ -1934,20 +1981,26 @@ void dppc_interpreter::ppc_lswx() { while (grab_inb > 0) { switch (grab_inb) { case 1: - stringed_word = mem_grab_byte(ppc_effective_address) << 24; + stringed_word = mmu_read_vmem(ppc_effective_address) << 24; + //stringed_word = mem_grab_byte(ppc_effective_address) << 24; ppc_state.gpr[reg_d] = stringed_word; grab_inb = 0; break; case 2: - stringed_word = mem_grab_byte(ppc_effective_address) << 24; - stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; + stringed_word = mmu_read_vmem(ppc_effective_address) << 24; + //stringed_word = mem_grab_byte(ppc_effective_address) << 24; + stringed_word += mmu_read_vmem(ppc_effective_address + 1) << 16; + //stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; ppc_state.gpr[reg_d] = stringed_word; grab_inb = 0; break; case 3: - stringed_word = mem_grab_byte(ppc_effective_address) << 24; - stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; - stringed_word += mem_grab_byte(ppc_effective_address + 2) << 8; + stringed_word = mmu_read_vmem(ppc_effective_address) << 24; + //stringed_word = mem_grab_byte(ppc_effective_address) << 24; + stringed_word += mmu_read_vmem(ppc_effective_address + 1) << 16; + //stringed_word += mem_grab_byte(ppc_effective_address + 1) << 16; + stringed_word += mmu_read_vmem(ppc_effective_address + 2) << 8; + //stringed_word += mem_grab_byte(ppc_effective_address + 2) << 8; ppc_state.gpr[reg_d] = stringed_word; grab_inb = 0; break; @@ -1973,22 +2026,29 @@ void dppc_interpreter::ppc_stswi() { while (grab_inb > 0) { switch (grab_inb) { case 1: - mem_write_byte(ppc_effective_address, (ppc_result_d >> 24)); + mmu_write_vmem(ppc_effective_address, (ppc_result_d >> 24)); + //mem_write_byte(ppc_effective_address, (ppc_result_d >> 24)); grab_inb = 0; break; case 2: - mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); - mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); + mmu_write_vmem(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); + //mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); + mmu_write_vmem((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); + //mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); grab_inb = 0; break; case 3: - mem_write_byte(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 + 2), ((ppc_result_d >> 8) & 0xFF)); + mmu_write_vmem(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); + //mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); + mmu_write_vmem((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); + //mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); + mmu_write_vmem((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF)); + //mem_write_byte((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF)); grab_inb = 0; break; default: - mem_write_dword(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_dword(ppc_effective_address, ppc_result_d); reg_s++; ppc_effective_address += 4; grab_inb -= 4; @@ -2007,22 +2067,29 @@ void dppc_interpreter::ppc_stswx() { while (grab_inb > 0) { switch (grab_inb) { case 1: - mem_write_byte(ppc_effective_address, (ppc_result_d >> 24)); + mmu_write_vmem(ppc_effective_address, (ppc_result_d >> 24)); + //mem_write_byte(ppc_effective_address, (ppc_result_d >> 24)); grab_inb = 0; break; case 2: - mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); - mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); + mmu_write_vmem(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); + //mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); + mmu_write_vmem((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); + //mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); grab_inb = 0; break; case 3: - mem_write_byte(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 + 2), ((ppc_result_d >> 8) & 0xFF)); + mmu_write_vmem(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); + //mem_write_byte(ppc_effective_address, ((ppc_result_d >> 24) & 0xFF)); + mmu_write_vmem((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); + //mem_write_byte((ppc_effective_address + 1), ((ppc_result_d >> 16) & 0xFF)); + mmu_write_vmem((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF)); + //mem_write_byte((ppc_effective_address + 2), ((ppc_result_d >> 8) & 0xFF)); grab_inb = 0; break; default: - mem_write_dword(ppc_effective_address, ppc_result_d); + mmu_write_vmem(ppc_effective_address, ppc_result_d); + //mem_write_dword(ppc_effective_address, ppc_result_d); reg_s++; ppc_effective_address += 4; grab_inb -= 4; @@ -2037,7 +2104,7 @@ void dppc_interpreter::ppc_tlbie() { num_supervisor_instrs++; #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() { diff --git a/main.cpp b/main.cpp index e6169ad..c3a3a2c 100644 --- a/main.cpp +++ b/main.cpp @@ -118,8 +118,10 @@ int main(int argc, char** argv) { loguru::init(argc, argv); loguru::add_file("dingusppc.log", loguru::Append, 0); } else { - loguru::g_stderr_verbosity = 0; + loguru::g_preamble_uptime = false; + loguru::g_stderr_verbosity = loguru::Verbosity_INFO; loguru::init(argc, argv); + loguru::add_file("exceptions.log", loguru::Truncate, -7); } if (*machine_opt) {