From 167c863409df447a798c4a77b4232baa48cf2dd4 Mon Sep 17 00:00:00 2001 From: ogamespec Date: Mon, 4 May 2020 19:00:40 +0300 Subject: [PATCH 1/9] describe_hid0 --- SRC/Core/Cache.h | 2 +- SRC/Core/Gekko.cpp | 10 ++---- SRC/Core/Gekko.h | 1 - SRC/Core/GekkoCommands.cpp | 56 +++++++++++++++++++++++++++++++++ SRC/Core/Interpreter/System.cpp | 6 ++++ SRC/Core/Jitc.cpp | 6 ++++ SRC/Core/Jitc.h | 2 ++ SRC/Core/JitcX64/Common.cpp | 2 +- SRC/Core/Readme.md | 6 ++-- 9 files changed, 78 insertions(+), 13 deletions(-) diff --git a/SRC/Core/Cache.h b/SRC/Core/Cache.h index 451232d8..28496fa4 100644 --- a/SRC/Core/Cache.h +++ b/SRC/Core/Cache.h @@ -38,7 +38,7 @@ namespace Gekko // You can disable cache emulation for debugging purposes. // This does not apply to a locked cache. - bool DisableForDebugReasons = true; + bool DisableForDebugReasons = false; uint8_t* LockedCache = nullptr; uint32_t LockedCacheAddr = 0; diff --git a/SRC/Core/Gekko.cpp b/SRC/Core/Gekko.cpp index 80ef5084..e58f1b2e 100644 --- a/SRC/Core/Gekko.cpp +++ b/SRC/Core/Gekko.cpp @@ -13,11 +13,11 @@ namespace Gekko { core->TestBreakpoints(); - //core->interp->ExecuteOpcode(); + core->interp->ExecuteOpcode(); // For debugging purposes, Jitc is not yet turned on when the code is uploaded to master. - core->jitc->Execute(); + //core->jitc->Execute(); } } @@ -120,12 +120,6 @@ namespace Gekko } } - void GekkoCore::TickForJitc() - { - Gekko::Gekko->Tick(); - Gekko::Gekko->ops++; - } - int64_t GekkoCore::GetTicks() { return regs.tb.sval; diff --git a/SRC/Core/Gekko.h b/SRC/Core/Gekko.h index 0c2c2161..6c0aa48a 100644 --- a/SRC/Core/Gekko.h +++ b/SRC/Core/Gekko.h @@ -160,7 +160,6 @@ namespace Gekko void Reset(); void Tick(); - static void TickForJitc(); int64_t GetTicks(); int64_t OneSecond(); int64_t OneMillisecond() { return msec; } diff --git a/SRC/Core/GekkoCommands.cpp b/SRC/Core/GekkoCommands.cpp index 300f5ece..5cdf6083 100644 --- a/SRC/Core/GekkoCommands.cpp +++ b/SRC/Core/GekkoCommands.cpp @@ -213,6 +213,61 @@ namespace Gekko else DBReport("MSR[LE] : 0, processor runs in big-endian mode\n"); } + // HID0 info + static void describe_hid0(uint32_t val) + { + DBReport("HID0: 0x%08X\n", val); + + if (val & HID0_EMCP) DBReport("HID0[EMCP] : 1, Asserting MCP causes checkstop or a machine check\n"); + else DBReport("HID0[EMCP] : 0, Masks MCP. Asserting MCP does not generate a machine check exception or a checkstop\n"); + if (val & HID0_DBP) DBReport("HID0[DBP] : 1, Disable parity generation\n"); + else DBReport("HID0[DBP] : 0, Parity generation is enabled\n"); + if (val & HID0_EBA) DBReport("HID0[EBA] : 1, Allows a address parity error to cause a checkstop or a machine check\n"); + else DBReport("HID0[EBA] : 0, Prevents address parity checking\n"); + if (val & HID0_EBD) DBReport("HID0[EBD] : 1, Allows a data parity error to cause a checkstop or machine check\n"); + else DBReport("HID0[EBD] : 0, Parity checking is disabled\n"); + if (val & HID0_PAR) DBReport("HID0[PAR] : 1, Alters bus protocol slightly by preventing the processor from driving ARTRY to high\n"); + else DBReport("HID0[PAR] : 0, Precharge of ARTRY enabled\n"); + if (val & HID0_DOZE) DBReport("HID0[DOZE] : 1, Doze mode enabled\n"); + else DBReport("HID0[DOZE] : 0, Doze mode disabled\n"); + if (val & HID0_NAP) DBReport("HID0[NAP] : 1, Nap mode enabled\n"); + else DBReport("HID0[NAP] : 0, Nap mode disabled\n"); + if (val & HID0_SLEEP) DBReport("HID0[SLEEP]: 1, Sleep mode enabled\n"); + else DBReport("HID0[SLEEP]: 0, Sleep mode disabled\n"); + if (val & HID0_DPM) DBReport("HID0[DPM] : 1, Dynamic power management is enabled\n"); + else DBReport("HID0[DPM] : 0, Dynamic power management is disabled\n"); + if (val & HID0_NHR) DBReport("HID0[NHR] : 1, Hard reset has not occurred\n"); + else DBReport("HID0[NHR] : 0, Hard reset occurred\n"); + if (val & HID0_ICE) DBReport("HID0[ICE] : 1, Instruction cache is enabled\n"); + else DBReport("HID0[ICE] : 0, Instruction cache is disabled\n"); + if (val & HID0_DCE) DBReport("HID0[DCE] : 1, Data cache is enabled\n"); + else DBReport("HID0[DCE] : 0, Data cache is disabled\n"); + if (val & HID0_ILOCK) DBReport("HID0[ILOCK]: 1, Instruction cache locked (frozen)\n"); + else DBReport("HID0[ILOCK]: 0, Instruction cache not locked\n"); + if (val & HID0_DLOCK) DBReport("HID0[DLOCK]: 1, Data cache locked (frozen)\n"); + else DBReport("HID0[DLOCK]: 0, Data cache not locked\n"); + if (val & HID0_ICFI) DBReport("HID0[ICFI] : 1, Instruction cache invalidating\n"); + else DBReport("HID0[ICFI] : 0, Instruction cache is not invalidated\n"); + if (val & HID0_DCFI) DBReport("HID0[DCFI] : 1, Data cache invalidating\n"); + else DBReport("HID0[DCFI] : 0, Data cache is not invalidated\n"); + if (val & HID0_SPD) DBReport("HID0[SPD] : 1, Speculative bus accesses to nonguarded space disabled\n"); + else DBReport("HID0[SPD] : 0, Speculative bus accesses to nonguarded space enabled\n"); + if (val & HID0_IFEM) DBReport("HID0[IFEM] : 1, Instruction fetches reflect the M bit from the WIM settings\n"); + else DBReport("HID0[IFEM] : 0, Instruction fetches M bit disabled\n"); + if (val & HID0_SGE) DBReport("HID0[SGE] : 1, Store gathering is enabled\n"); + else DBReport("HID0[SGE] : 0, Store gathering is disabled \n"); + if (val & HID0_DCFA) DBReport("HID0[DCFA] : 1, Data cache flush assist facility is enabled\n"); + else DBReport("HID0[DCFA] : 0, Data cache flush assist facility is disabled\n"); + if (val & HID0_BTIC) DBReport("HID0[BTIC] : 1, BTIC is enabled\n"); + else DBReport("HID0[BTIC] : 0, BTIC is disabled\n"); + if (val & HID0_ABE) DBReport("HID0[ABE] : 1, Address-only operations are broadcast on the 60x bus\n"); + else DBReport("HID0[ABE] : 0, Address-only operations affect only local L1 and L2 caches and are not broadcast\n"); + if (val & HID0_BHT) DBReport("HID0[BHT] : 1, Branch history enabled\n"); + else DBReport("HID0[BHT] : 0, Branch history disabled\n"); + if (val & HID0_NOOPTI) DBReport("HID0[NOOPTI]: 1, The dcbt and dcbtst instructions are no-oped globally\n"); + else DBReport("HID0[NOOPTI]: 0, The dcbt and dcbtst instructions are enabled\n"); + } + static Json::Value* cmd_r(std::vector& args) { uint32_t(*op)(uint32_t a, uint32_t b) = NULL; @@ -228,6 +283,7 @@ namespace Gekko if (args.size() <= 3) { if (!_stricmp(args[1].c_str(), "msr")) describe_msr(*n); + else if (!_stricmp(args[1].c_str(), "hid0")) describe_hid0(*n); else DBReport("%s = %i (0x%X)\n", args[1].c_str(), *n, *n); return nullptr; } diff --git a/SRC/Core/Interpreter/System.cpp b/SRC/Core/Interpreter/System.cpp index 5e720a9a..c977bb11 100644 --- a/SRC/Core/Interpreter/System.cpp +++ b/SRC/Core/Interpreter/System.cpp @@ -195,12 +195,18 @@ namespace Gekko Gekko->cache.Freeze((bits & HID0_DLOCK) ? true : false); if (bits & HID0_DCFI) { + bits &= ~HID0_DCFI; Gekko->cache.Reset(); } if (bits & HID0_ICFI) { + bits &= ~HID0_ICFI; Gekko->jitc->Reset(); } + + Gekko->regs.spr[spr] = bits; + Gekko->regs.pc += 4; + return; } break; diff --git a/SRC/Core/Jitc.cpp b/SRC/Core/Jitc.cpp index 0e36fdcd..cb153ad6 100644 --- a/SRC/Core/Jitc.cpp +++ b/SRC/Core/Jitc.cpp @@ -199,6 +199,12 @@ namespace Gekko InvalidateAll(); } + void Jitc::Tick() + { + Gekko->Tick(); + Gekko->ops++; + } + void Jitc::CompileInstr(AnalyzeInfo* info, CodeSegment* seg) { switch (info->instr) diff --git a/SRC/Core/Jitc.h b/SRC/Core/Jitc.h index 5ee58195..af833e12 100644 --- a/SRC/Core/Jitc.h +++ b/SRC/Core/Jitc.h @@ -78,6 +78,8 @@ namespace Gekko static void __fastcall ReadDouble(uint32_t addr, uint64_t* reg) { Gekko->ReadDouble(addr, reg); } static void __fastcall WriteDouble(uint32_t addr, uint64_t* data) { Gekko->WriteDouble(addr, data); } + static void Tick(); + // This segment is not involved in invalidation, so as not to disrupt the code. CodeSegment* currentSegment = nullptr; diff --git a/SRC/Core/JitcX64/Common.cpp b/SRC/Core/JitcX64/Common.cpp index 4eb6b166..bfa4bbf5 100644 --- a/SRC/Core/JitcX64/Common.cpp +++ b/SRC/Core/JitcX64/Common.cpp @@ -82,7 +82,7 @@ namespace Gekko //7: 12 00 00 //17: ff d0 call rax - uint64_t fnPtr = (uint64_t)GekkoCore::TickForJitc; + uint64_t fnPtr = (uint64_t)Jitc::Tick; seg->Write16(0xb848); seg->Write64(fnPtr); diff --git a/SRC/Core/Readme.md b/SRC/Core/Readme.md index 99777754..2e65ac8c 100644 --- a/SRC/Core/Readme.md +++ b/SRC/Core/Readme.md @@ -26,7 +26,7 @@ Used in the interpreter to easily get the Overflow and Carry flags. They are obt GekkoCore supports MMU emulation, while it is still an experimental feature that requires debugging. Subsequently, as the MMU will work more or less correctly, the TLB functionality will gradually turn on. -TLB is the history of MMU translations, to speed up address translation. TLB is implemented as `std :: unordered_map`. +TLB is the history of MMU translations, to speed up address translation. TLB is implemented as `std::unordered_map`. ## Cache Support @@ -82,7 +82,9 @@ From time to time, an emulated program loads new software modules (overlays). In Gekko has a handy mechanism for tracking this. The `icbi` instruction is used to discard the old recompiled code. -The recompiler is also invalidated after setting or removing breakpoints. +The recompiler is also invalidated after setting or removing breakpoints and several other cases. + +The current executable segment is not invalidated, as this will lead to an exception. ### Running Recompiled Code From f282e08c0ec91418e6e1ce0aa8cdabcbf85644c5 Mon Sep 17 00:00:00 2001 From: ogamespec Date: Mon, 4 May 2020 19:45:20 +0300 Subject: [PATCH 2/9] Cache debug commands - MMU WIMG is parameter --- Data/GekkoCoreJdi.json | 11 +++++++ SRC/Core/Cache.h | 2 ++ SRC/Core/Gekko.cpp | 6 ++-- SRC/Core/Gekko.h | 11 ++++--- SRC/Core/GekkoCommands.cpp | 8 +++++ SRC/Core/Interpreter.cpp | 6 ++-- SRC/Core/Interpreter/LoadStore.cpp | 3 +- SRC/Core/Interpreter/System.cpp | 32 +++++++++++++++----- SRC/Core/Jitc.cpp | 3 +- SRC/Core/MemoryHub.cpp | 48 +++++++++++++++++------------- SRC/Core/Mmu.cpp | 34 ++++++++++----------- SRC/Debugger/cmd.cpp | 15 ++++++---- SRC/Debugger/cpuview.cpp | 9 ++++-- SRC/Debugger/memview.cpp | 9 ++++-- SRC/Dolwin/Loader.cpp | 3 +- SRC/HighLevel/DumpThreads.cpp | 12 ++++++-- SRC/HighLevel/Stdc.cpp | 14 +++++---- 17 files changed, 147 insertions(+), 79 deletions(-) diff --git a/Data/GekkoCoreJdi.json b/Data/GekkoCoreJdi.json index 76911100..d2743e08 100644 --- a/Data/GekkoCoreJdi.json +++ b/Data/GekkoCoreJdi.json @@ -60,6 +60,17 @@ "bc": { "help": "Clear Gekko breakpoints", + }, + + "CacheLog": { + "help": "Set cache operations log mode", + "args": 1, + "usage": [ + "Syntax: CacheLog <0|1|2>", + "0: None (disabled)", + "1: Show commands (cache control instructions activity)", + "2: Show all operations (load/store, cast-in/cast-out, etc.)" + ] } } } diff --git a/SRC/Core/Cache.h b/SRC/Core/Cache.h index 28496fa4..7146186f 100644 --- a/SRC/Core/Cache.h +++ b/SRC/Core/Cache.h @@ -79,5 +79,7 @@ namespace Gekko void __fastcall WriteDouble(uint32_t addr, uint64_t* data); void LockedCacheDma(bool MemToCache, uint32_t memaddr, uint32_t lcaddr, size_t bursts); + + void SetLogLevel(CacheLogLevel level) { log = level; } }; } diff --git a/SRC/Core/Gekko.cpp b/SRC/Core/Gekko.cpp index e58f1b2e..d9d54321 100644 --- a/SRC/Core/Gekko.cpp +++ b/SRC/Core/Gekko.cpp @@ -267,10 +267,10 @@ namespace Gekko return Gekko->interp->ExecuteInterpeterFallback(); } - uint32_t GekkoCore::EffectiveToPhysical(uint32_t ea, MmuAccess type) + uint32_t GekkoCore::EffectiveToPhysical(uint32_t ea, MmuAccess type, int& WIMG) { - //return EffectiveToPhysicalNoMmu(ea, type); - return EffectiveToPhysicalMmu(ea, type); + //return EffectiveToPhysicalNoMmu(ea, type, WIMG); + return EffectiveToPhysicalMmu(ea, type, WIMG); } void GekkoCore::AddBreakpoint(uint32_t addr) diff --git a/SRC/Core/Gekko.h b/SRC/Core/Gekko.h index 6c0aa48a..34932a4b 100644 --- a/SRC/Core/Gekko.h +++ b/SRC/Core/Gekko.h @@ -115,15 +115,14 @@ namespace Gekko size_t ops; // instruction counter (only for debug!) size_t segmentsExecuted; // The number of completed recompiler segments. - uint32_t __fastcall EffectiveToPhysicalNoMmu(uint32_t ea, MmuAccess type); - uint32_t __fastcall EffectiveToPhysicalMmu(uint32_t ea, MmuAccess type); + uint32_t __fastcall EffectiveToPhysicalNoMmu(uint32_t ea, MmuAccess type, int& WIMG); + uint32_t __fastcall EffectiveToPhysicalMmu(uint32_t ea, MmuAccess type, int& WIMG); volatile bool decreq = false; // decrementer exception request volatile bool intFlag = false; // INT signal volatile bool exception = false; // exception pending MmuResult MmuLastResult = MmuResult::Ok; - int LastWIMG = 0; // The value of the WIMG bits after the last address translation. // For convenient access to BAT registers (Mmu related) uint32_t *dbatu[4]; @@ -131,8 +130,8 @@ namespace Gekko uint32_t *ibatu[4]; uint32_t *ibatl[4]; - bool __fastcall BlockAddressTranslation(uint32_t ea, uint32_t& pa, MmuAccess type); - uint32_t __fastcall SegmentTranslation(uint32_t ea, MmuAccess type); + bool __fastcall BlockAddressTranslation(uint32_t ea, uint32_t& pa, MmuAccess type, int& WIMG); + uint32_t __fastcall SegmentTranslation(uint32_t ea, MmuAccess type, int& WIMG); TLB tlb; @@ -190,7 +189,7 @@ namespace Gekko void __fastcall WriteDouble(uint32_t addr, uint64_t* data); // Translate address by Mmu - uint32_t EffectiveToPhysical(uint32_t ea, MmuAccess type); + uint32_t EffectiveToPhysical(uint32_t ea, MmuAccess type, int & WIMG); static void SwapArea(uint32_t* addr, int count); static void SwapAreaHalf(uint16_t* addr, int count); diff --git a/SRC/Core/GekkoCommands.cpp b/SRC/Core/GekkoCommands.cpp index 5cdf6083..0434838e 100644 --- a/SRC/Core/GekkoCommands.cpp +++ b/SRC/Core/GekkoCommands.cpp @@ -349,6 +349,13 @@ namespace Gekko return nullptr; } + static Json::Value* CacheLog(std::vector& args) + { + CacheLogLevel level = (CacheLogLevel)atoi(args[1].c_str()); + Gekko->cache.SetLogLevel(level); + return nullptr; + } + void gekko_init_handlers() { Debug::Hub.AddCmd("run", cmd_run); @@ -358,5 +365,6 @@ namespace Gekko Debug::Hub.AddCmd("br", cmd_br); Debug::Hub.AddCmd("bw", cmd_bw); Debug::Hub.AddCmd("bc", cmd_bc); + Debug::Hub.AddCmd("CacheLog", CacheLog); } } diff --git a/SRC/Core/Interpreter.cpp b/SRC/Core/Interpreter.cpp index 45707d64..8851dd16 100644 --- a/SRC/Core/Interpreter.cpp +++ b/SRC/Core/Interpreter.cpp @@ -6,12 +6,13 @@ namespace Gekko // parse and execute single opcode void Interpreter::ExecuteOpcode() { + int WIMG; uint32_t op, pa; // execute one instruction // (possible CPU_EXCEPTION_DSI, ISI, ALIGN, PROGRAM, FPUNAVAIL, SYSCALL) //pa = core->EffectiveToPhysical(Gekko->regs.pc, MmuAccess::Execute); - pa = core->EffectiveToPhysicalNoMmu(Gekko->regs.pc, MmuAccess::Execute); + pa = core->EffectiveToPhysicalNoMmu(Gekko->regs.pc, MmuAccess::Execute, WIMG); if (pa == Gekko::BadAddress) { Gekko->Exception(Exception::ISI); @@ -49,12 +50,13 @@ namespace Gekko bool Interpreter::ExecuteInterpeterFallback() { + int WIMG; uint32_t op, pa; // execute one instruction // (possible CPU_EXCEPTION_DSI, ISI, ALIGN, PROGRAM, FPUNAVAIL, SYSCALL) //pa = core->EffectiveToPhysical(core->regs.pc, MmuAccess::Execute); - pa = core->EffectiveToPhysicalNoMmu(Gekko->regs.pc, MmuAccess::Execute); + pa = core->EffectiveToPhysicalNoMmu(Gekko->regs.pc, MmuAccess::Execute, WIMG); if (pa == Gekko::BadAddress) { Gekko->Exception(Exception::ISI); diff --git a/SRC/Core/Interpreter/LoadStore.cpp b/SRC/Core/Interpreter/LoadStore.cpp index 424dc5c0..befe594c 100644 --- a/SRC/Core/Interpreter/LoadStore.cpp +++ b/SRC/Core/Interpreter/LoadStore.cpp @@ -495,10 +495,11 @@ namespace Gekko // rd = MEM(ea, 4) OP(LWARX) { + int WIMG; uint32_t ea = RRB; if (RA) ea += RRA; Gekko->interp->RESERVE = true; - Gekko->interp->RESERVE_ADDR = Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Read); + Gekko->interp->RESERVE_ADDR = Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Read, WIMG); Gekko->ReadWord(ea, &RRD); if (Gekko->exception) return; Gekko->regs.pc += 4; diff --git a/SRC/Core/Interpreter/System.cpp b/SRC/Core/Interpreter/System.cpp index c977bb11..08cfc095 100644 --- a/SRC/Core/Interpreter/System.cpp +++ b/SRC/Core/Interpreter/System.cpp @@ -196,12 +196,18 @@ namespace Gekko if (bits & HID0_DCFI) { bits &= ~HID0_DCFI; - Gekko->cache.Reset(); + + // On a real system, after a global cache invalidation, the data still remains in the L2 cache. + // We cannot afford global invalidation, as the L2 cache is not supported. + + DBReport2(DbgChannel::CPU, "Data Cache Flash Invalidate\n"); } if (bits & HID0_ICFI) { bits &= ~HID0_ICFI; Gekko->jitc->Reset(); + + DBReport2(DbgChannel::CPU, "Instruction Cache Flash Invalidate\n"); } Gekko->regs.spr[spr] = bits; @@ -415,12 +421,14 @@ namespace Gekko OP(DCBT) { + int WIMG; + if (Gekko->regs.spr[(int)Gekko::SPR::HID0] & HID0_NOOPTI) return; uint32_t ea = RA ? RRA + RRB : RRB; - uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Read); + uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Read, WIMG); if (pa != Gekko::BadAddress) { Gekko->cache.Touch(pa); @@ -430,6 +438,8 @@ namespace Gekko OP(DCBTST) { + int WIMG; + if (Gekko->regs.spr[(int)Gekko::SPR::HID0] & HID0_NOOPTI) return; @@ -437,7 +447,7 @@ namespace Gekko // TouchForStore is also made architecturally as a Read operation so that the MMU does not set the "Changed" bit for PTE. - uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Read); + uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Read, WIMG); if (pa != Gekko::BadAddress) { Gekko->cache.TouchForStore(pa); @@ -447,9 +457,10 @@ namespace Gekko OP(DCBZ) { + int WIMG; uint32_t ea = RA ? RRA + RRB : RRB; - uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Write); + uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Write, WIMG); if (pa != Gekko::BadAddress) { Gekko->cache.Zero(pa); @@ -469,6 +480,8 @@ namespace Gekko OP(DCBZ_L) { + int WIMG; + if (!Gekko->cache.IsLockedEnable()) { Gekko->PrCause = PrivilegedCause::IllegalInstruction; @@ -478,7 +491,7 @@ namespace Gekko uint32_t ea = RA ? RRA + RRB : RRB; - uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Write); + uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Write, WIMG); if (pa != Gekko::BadAddress) { Gekko->cache.ZeroLocked(pa); @@ -494,9 +507,10 @@ namespace Gekko OP(DCBST) { + int WIMG; uint32_t ea = RA ? RRA + RRB : RRB; - uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Read); + uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Read, WIMG); if (pa != Gekko::BadAddress) { Gekko->cache.Store(pa); @@ -512,9 +526,10 @@ namespace Gekko OP(DCBF) { + int WIMG; uint32_t ea = RA ? RRA + RRB : RRB; - uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Read); + uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Read, WIMG); if (pa != Gekko::BadAddress) { Gekko->cache.Flush(pa); @@ -530,6 +545,7 @@ namespace Gekko OP(DCBI) { + int WIMG; uint32_t ea = RA ? RRA + RRB : RRB; if (Gekko->regs.msr & MSR_PR) @@ -539,7 +555,7 @@ namespace Gekko return; } - uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Write); + uint32_t pa = Gekko->EffectiveToPhysical(ea, MmuAccess::Write, WIMG); if (pa != Gekko::BadAddress) { Gekko->cache.Invalidate(pa); diff --git a/SRC/Core/Jitc.cpp b/SRC/Core/Jitc.cpp index cb153ad6..6933f279 100644 --- a/SRC/Core/Jitc.cpp +++ b/SRC/Core/Jitc.cpp @@ -44,7 +44,8 @@ namespace Gekko if (core->TestBreakpointForJitc(addr)) break; - uint32_t physicalAddress = core->EffectiveToPhysical(addr, MmuAccess::Execute); + int WIMG; + uint32_t physicalAddress = core->EffectiveToPhysical(addr, MmuAccess::Execute, WIMG); uint32_t instr; // TODO: This moment needs to be rethinked. It makes little sense to generate ISI in the compilation process, diff --git a/SRC/Core/MemoryHub.cpp b/SRC/Core/MemoryHub.cpp index 8f22dcf8..54f2f405 100644 --- a/SRC/Core/MemoryHub.cpp +++ b/SRC/Core/MemoryHub.cpp @@ -10,9 +10,10 @@ namespace Gekko void __fastcall GekkoCore::ReadByte(uint32_t addr, uint32_t *reg) { + int WIMG; TestReadBreakpoints(addr); - uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Read); + uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Read, WIMG); if (pa == BadAddress) { regs.spr[(int)SPR::DAR] = addr; @@ -20,7 +21,7 @@ namespace Gekko return; } - if (cache.IsEnabled() && (LastWIMG & WIMG_I) == 0) + if (cache.IsEnabled() && (WIMG & WIMG_I) == 0) { cache.ReadByte(pa, reg); return; @@ -37,9 +38,10 @@ namespace Gekko void __fastcall GekkoCore::WriteByte(uint32_t addr, uint32_t data) { + int WIMG; TestWriteBreakpoints(addr); - uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Write); + uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Write, WIMG); if (pa == BadAddress) { regs.spr[(int)SPR::DAR] = addr; @@ -56,10 +58,10 @@ namespace Gekko } } - if (cache.IsEnabled() && (LastWIMG & WIMG_I) == 0) + if (cache.IsEnabled() && (WIMG & WIMG_I) == 0) { cache.WriteByte(pa, data); - if ((LastWIMG & WIMG_W) == 0) + if ((WIMG & WIMG_W) == 0) return; } @@ -74,9 +76,10 @@ namespace Gekko void __fastcall GekkoCore::ReadHalf(uint32_t addr, uint32_t *reg) { + int WIMG; TestReadBreakpoints(addr); - uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Read); + uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Read, WIMG); if (pa == BadAddress) { regs.spr[(int)SPR::DAR] = addr; @@ -84,7 +87,7 @@ namespace Gekko return; } - if (cache.IsEnabled() && (LastWIMG & WIMG_I) == 0) + if (cache.IsEnabled() && (WIMG & WIMG_I) == 0) { cache.ReadHalf(pa, reg); return; @@ -107,9 +110,10 @@ namespace Gekko void __fastcall GekkoCore::WriteHalf(uint32_t addr, uint32_t data) { + int WIMG; TestWriteBreakpoints(addr); - uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Write); + uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Write, WIMG); if (pa == BadAddress) { regs.spr[(int)SPR::DAR] = addr; @@ -126,10 +130,10 @@ namespace Gekko } } - if (cache.IsEnabled() && (LastWIMG & WIMG_I) == 0) + if (cache.IsEnabled() && (WIMG & WIMG_I) == 0) { cache.WriteHalf(pa, data); - if ((LastWIMG & WIMG_W) == 0) + if ((WIMG & WIMG_W) == 0) return; } @@ -144,9 +148,10 @@ namespace Gekko void __fastcall GekkoCore::ReadWord(uint32_t addr, uint32_t *reg) { + int WIMG; TestReadBreakpoints(addr); - uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Read); + uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Read, WIMG); if (pa == BadAddress) { regs.spr[(int)SPR::DAR] = addr; @@ -154,7 +159,7 @@ namespace Gekko return; } - if (cache.IsEnabled() && (LastWIMG & WIMG_I) == 0) + if (cache.IsEnabled() && (WIMG & WIMG_I) == 0) { cache.ReadWord(pa, reg); return; @@ -171,9 +176,10 @@ namespace Gekko void __fastcall GekkoCore::WriteWord(uint32_t addr, uint32_t data) { + int WIMG; TestWriteBreakpoints(addr); - uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Write); + uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Write, WIMG); if (pa == BadAddress) { regs.spr[(int)SPR::DAR] = addr; @@ -190,10 +196,10 @@ namespace Gekko } } - if (cache.IsEnabled() && (LastWIMG & WIMG_I) == 0) + if (cache.IsEnabled() && (WIMG & WIMG_I) == 0) { cache.WriteWord(pa, data); - if ((LastWIMG & WIMG_W) == 0) + if ((WIMG & WIMG_W) == 0) return; } @@ -208,9 +214,10 @@ namespace Gekko void __fastcall GekkoCore::ReadDouble(uint32_t addr, uint64_t *reg) { + int WIMG; TestReadBreakpoints(addr); - uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Read); + uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Read, WIMG); if (pa == BadAddress) { regs.spr[(int)SPR::DAR] = addr; @@ -218,7 +225,7 @@ namespace Gekko return; } - if (cache.IsEnabled() && (LastWIMG & WIMG_I) == 0) + if (cache.IsEnabled() && (WIMG & WIMG_I) == 0) { cache.ReadDouble(pa, reg); return; @@ -237,9 +244,10 @@ namespace Gekko void __fastcall GekkoCore::WriteDouble(uint32_t addr, uint64_t *data) { + int WIMG; TestWriteBreakpoints(addr); - uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Write); + uint32_t pa = EffectiveToPhysical(addr, MmuAccess::Write, WIMG); if (pa == BadAddress) { regs.spr[(int)SPR::DAR] = addr; @@ -256,10 +264,10 @@ namespace Gekko } } - if (cache.IsEnabled() && (LastWIMG & WIMG_I) == 0) + if (cache.IsEnabled() && (WIMG & WIMG_I) == 0) { cache.WriteDouble(pa, data); - if ((LastWIMG & WIMG_W) == 0) + if ((WIMG & WIMG_W) == 0) return; } diff --git a/SRC/Core/Mmu.cpp b/SRC/Core/Mmu.cpp index 21c2b73b..d115aee6 100644 --- a/SRC/Core/Mmu.cpp +++ b/SRC/Core/Mmu.cpp @@ -1,8 +1,6 @@ // MMU never throws Gekko exceptions. If something went wrong, BadAddress is returned. Then the consumer decides what to do. -// The result of the MMU is placed in two variables (GekkoCore): -// - LastWIMG -// - MmuLastResult +// The result of the MMU is placed in MmuLastResult and translated address as output. // We also use BadAddress as a signal that the translation did not pass (a special address that is usually not used by anyone). @@ -13,14 +11,14 @@ namespace Gekko // A simple translation, which is configured by the Dolphin OS software environment (until it starts using MMU for ARAM mapping). - uint32_t __fastcall GekkoCore::EffectiveToPhysicalNoMmu(uint32_t ea, MmuAccess type) + uint32_t __fastcall GekkoCore::EffectiveToPhysicalNoMmu(uint32_t ea, MmuAccess type, int& WIMG) { - LastWIMG = WIMG_I; // Caching inhibited + WIMG = WIMG_I; // Caching inhibited // Locked cache if ((ea & ~0x3fff) == DOLPHIN_OS_LOCKED_CACHE_ADDRESS && cache.IsLockedEnable()) { - LastWIMG = 0; + WIMG = 0; return ea; } @@ -36,23 +34,23 @@ namespace Gekko // Native address translation defined by PowerPC architecture. There are some alien moments (Hash for Page Tables), but overall its fine. - uint32_t __fastcall GekkoCore::EffectiveToPhysicalMmu(uint32_t ea, MmuAccess type) + uint32_t __fastcall GekkoCore::EffectiveToPhysicalMmu(uint32_t ea, MmuAccess type, int& WIMG) { uint32_t pa; - LastWIMG = 0; + WIMG = 0; // First, try the block translation, if it doesnt work, try the Page Table. - if (!BlockAddressTranslation(ea, pa, type)) + if (!BlockAddressTranslation(ea, pa, type, WIMG)) { - pa = SegmentTranslation(ea, type); + pa = SegmentTranslation(ea, type, WIMG); } return pa; } - bool __fastcall GekkoCore::BlockAddressTranslation(uint32_t ea, uint32_t &pa, MmuAccess type) + bool __fastcall GekkoCore::BlockAddressTranslation(uint32_t ea, uint32_t &pa, MmuAccess type, int& WIMG) { // Ignore BAT access rights for now (not used in embodiment system) @@ -60,7 +58,7 @@ namespace Gekko { if ((regs.msr & MSR_IR) == 0) { - LastWIMG = WIMG_G; + WIMG = WIMG_G; pa = ea; return true; } @@ -78,7 +76,7 @@ namespace Gekko { pa = BATBRPN(*ibatl[n]) | ((ea >> 17) & bl); pa = (pa << 17) | (ea & 0x1ffff); - LastWIMG = (*ibatl[n] >> 3) & 0xf; + WIMG = (*ibatl[n] >> 3) & 0xf; MmuLastResult = MmuResult::Ok; return true; } @@ -88,7 +86,7 @@ namespace Gekko { if ((regs.msr & MSR_DR) == 0) { - LastWIMG = WIMG_M | WIMG_G; + WIMG = WIMG_M | WIMG_G; pa = ea; return true; } @@ -106,7 +104,7 @@ namespace Gekko { pa = BATBRPN(*dbatl[n]) | ((ea >> 17) & bl); pa = (pa << 17) | (ea & 0x1ffff); - LastWIMG = (*dbatl[n] >> 3) & 0xf; + WIMG = (*dbatl[n] >> 3) & 0xf; MmuLastResult = MmuResult::Ok; return true; } @@ -118,7 +116,7 @@ namespace Gekko return false; } - uint32_t __fastcall GekkoCore::SegmentTranslation(uint32_t ea, MmuAccess type) + uint32_t __fastcall GekkoCore::SegmentTranslation(uint32_t ea, MmuAccess type, int& WIMG) { int ptegUpper; @@ -240,7 +238,7 @@ namespace Gekko uint32_t pa = (pte[1] & ~0xfff) | (ea & 0xfff); if (type != MmuAccess::Execute) { - LastWIMG = (pte[1] >> 3) & 0xf; + WIMG = (pte[1] >> 3) & 0xf; } MmuLastResult = MmuResult::Ok; return pa; @@ -329,7 +327,7 @@ namespace Gekko uint32_t pa = (pte[1] & ~0xfff) | (ea & 0xfff); if (type != MmuAccess::Execute) { - LastWIMG = (pte[1] >> 3) & 0xf; + WIMG = (pte[1] >> 3) & 0xf; } MmuLastResult = MmuResult::Ok; return pa; diff --git a/SRC/Debugger/cmd.cpp b/SRC/Debugger/cmd.cpp index 9d5a79f8..8a1305d5 100644 --- a/SRC/Debugger/cmd.cpp +++ b/SRC/Debugger/cmd.cpp @@ -131,11 +131,12 @@ Json::Value* cmd_blr(std::vector& args) { if(emu.loaded) return nullptr; + int WIMG; uint32_t ea = con.disa_cursor; uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Execute); + pa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Execute, WIMG); } if(pa == Gekko::BadAddress) return nullptr; @@ -448,7 +449,8 @@ Json::Value* cmd_lr(std::vector& args) uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(sp, Gekko::MmuAccess::Execute); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(sp, Gekko::MmuAccess::Execute, WIMG); } if(!sp || pa == Gekko::BadAddress) break; @@ -489,7 +491,8 @@ Json::Value* cmd_nop(std::vector& args) uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Execute); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Execute, WIMG); } if(pa == Gekko::BadAddress) return nullptr; @@ -510,7 +513,8 @@ Json::Value* cmd_denop(std::vector& args) uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Execute); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Execute, WIMG); } if(pa == Gekko::BadAddress) return nullptr; @@ -549,7 +553,8 @@ Json::Value* cmd_sop(std::vector& args) uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(saddr, Gekko::MmuAccess::Execute); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(saddr, Gekko::MmuAccess::Execute, WIMG); } if(pa != Gekko::BadAddress) Gekko::Gekko->ReadWord(pa, &op); disa.instr = op; diff --git a/SRC/Debugger/cpuview.cpp b/SRC/Debugger/cpuview.cpp index 3768b479..78d75c36 100644 --- a/SRC/Debugger/cpuview.cpp +++ b/SRC/Debugger/cpuview.cpp @@ -78,7 +78,8 @@ void con_update_disa_window() uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(con.disa_cursor, Gekko::MmuAccess::Execute); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(con.disa_cursor, Gekko::MmuAccess::Execute, WIMG); } con_attr(0, 3); @@ -101,7 +102,8 @@ void con_update_disa_window() if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute, WIMG); if (pa != Gekko::BadAddress) { MIReadWord(pa, &op); @@ -149,7 +151,8 @@ static void disa_navigate() uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute, WIMG); } if (pa != Gekko::BadAddress) { diff --git a/SRC/Debugger/memview.cpp b/SRC/Debugger/memview.cpp index ea2a7fa1..090fa021 100644 --- a/SRC/Debugger/memview.cpp +++ b/SRC/Debugger/memview.cpp @@ -10,7 +10,8 @@ static const char *hexbyte(uint32_t addr) if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Read); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Read, WIMG); } if (mi.ram) @@ -37,7 +38,8 @@ static const char *charbyte(uint32_t addr) if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Read); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Read, WIMG); } if (mi.ram && pa != Gekko::BadAddress) @@ -63,7 +65,8 @@ void con_update_dump_window() uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(con.data, Gekko::MmuAccess::Read); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(con.data, Gekko::MmuAccess::Read, WIMG); } con_attr(0, 3); diff --git a/SRC/Dolwin/Loader.cpp b/SRC/Dolwin/Loader.cpp index 7834b2a3..c038cb9b 100644 --- a/SRC/Dolwin/Loader.cpp +++ b/SRC/Dolwin/Loader.cpp @@ -456,7 +456,8 @@ void ApplyPatches(bool load, int32_t a, int32_t b) uint32_t pa = (uint32_t)-1; if (Gekko::Gekko) { - pa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Execute); + int WIMG; + pa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Execute, WIMG); } if(pa == Gekko::BadAddress) continue; diff --git a/SRC/HighLevel/DumpThreads.cpp b/SRC/HighLevel/DumpThreads.cpp index 3048571f..4b9ee069 100644 --- a/SRC/HighLevel/DumpThreads.cpp +++ b/SRC/HighLevel/DumpThreads.cpp @@ -10,9 +10,11 @@ namespace HLE static bool LoadOsThread(uint32_t ea, OSThread* thread) { + int WIMG; + // Translate effective address - uint32_t threadPa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Read); + uint32_t threadPa = Gekko::Gekko->EffectiveToPhysical(ea, Gekko::MmuAccess::Read, WIMG); if (threadPa == Gekko::BadAddress) { DBReport("Invalid thread effective address: 0x%08X\n", ea); @@ -58,11 +60,13 @@ namespace HLE Json::Value* DumpDolphinOsThreads(bool displayOnScreen) { + int WIMG; + // Get pointer to __OSLinkActive uint32_t linkActiveEffectiveAddr = OS_LINK_ACTIVE; - uint32_t linkActivePa = Gekko::Gekko->EffectiveToPhysical(linkActiveEffectiveAddr, Gekko::MmuAccess::Read); + uint32_t linkActivePa = Gekko::Gekko->EffectiveToPhysical(linkActiveEffectiveAddr, Gekko::MmuAccess::Read, WIMG); if (linkActivePa == Gekko::BadAddress) { if (displayOnScreen) @@ -134,9 +138,11 @@ namespace HLE Json::Value* DumpDolphinOsContext(uint32_t effectiveAddr, bool displayOnScreen) { + int WIMG; + // Get context pointer - uint32_t physAddr = Gekko::Gekko->EffectiveToPhysical(effectiveAddr, Gekko::MmuAccess::Read); + uint32_t physAddr = Gekko::Gekko->EffectiveToPhysical(effectiveAddr, Gekko::MmuAccess::Read, WIMG); if (physAddr == Gekko::BadAddress) { diff --git a/SRC/HighLevel/Stdc.cpp b/SRC/HighLevel/Stdc.cpp index 89395e49..8237bf83 100644 --- a/SRC/HighLevel/Stdc.cpp +++ b/SRC/HighLevel/Stdc.cpp @@ -27,9 +27,10 @@ static void swap_double(void* srcPtr) // void *memcpy( void *dest, const void *src, size_t count); void HLE_memcpy() { + int WIMG; uint32_t eaDest = PARAM(0), eaSrc = PARAM(1), cnt = PARAM(2); - uint32_t paDest = Gekko::Gekko->EffectiveToPhysical(eaDest, Gekko::MmuAccess::Read); - uint32_t paSrc = Gekko::Gekko->EffectiveToPhysical(eaSrc, Gekko::MmuAccess::Read); + uint32_t paDest = Gekko::Gekko->EffectiveToPhysical(eaDest, Gekko::MmuAccess::Read, WIMG); + uint32_t paSrc = Gekko::Gekko->EffectiveToPhysical(eaSrc, Gekko::MmuAccess::Read, WIMG); assert( paDest != Gekko::BadAddress); assert( paSrc != Gekko::BadAddress); @@ -45,8 +46,9 @@ void HLE_memcpy() // void *memset( void *dest, int c, size_t count); void HLE_memset() { + int WIMG; uint32_t eaDest = PARAM(0), c = PARAM(1), cnt = PARAM(2); - uint32_t paDest = Gekko::Gekko->EffectiveToPhysical(eaDest, Gekko::MmuAccess::Read); + uint32_t paDest = Gekko::Gekko->EffectiveToPhysical(eaDest, Gekko::MmuAccess::Read, WIMG); assert(paDest != Gekko::BadAddress); assert( (paDest + cnt) < RAMSIZE); @@ -81,7 +83,8 @@ void HLE_cos() // double modf(double x, double * intptr) void HLE_modf() { - double * intptr = (double *)(&mi.ram[Gekko::Gekko->EffectiveToPhysical(PARAM(0), Gekko::MmuAccess::Read)]); + int WIMG; + double * intptr = (double *)(&mi.ram[Gekko::Gekko->EffectiveToPhysical(PARAM(0), Gekko::MmuAccess::Read, WIMG)]); FPRD(1) = modf(FPRD(1), intptr); swap_double(intptr); @@ -90,7 +93,8 @@ void HLE_modf() // double frexp(double x, int * expptr) void HLE_frexp() { - uint32_t * expptr = (uint32_t *)(&mi.ram[Gekko::Gekko->EffectiveToPhysical(PARAM(0), Gekko::MmuAccess::Read)]); + int WIMG; + uint32_t * expptr = (uint32_t *)(&mi.ram[Gekko::Gekko->EffectiveToPhysical(PARAM(0), Gekko::MmuAccess::Read, WIMG)]); FPRD(1) = frexp(FPRD(1), (int *)expptr); *expptr = SWAP(*expptr); From d1f1de389d7cc113108f3dea6d2c5a6f43038d7f Mon Sep 17 00:00:00 2001 From: ogamespec Date: Tue, 5 May 2020 03:07:13 +0300 Subject: [PATCH 3/9] Debugger Step Over functionality --- SRC/Core/Gekko.cpp | 22 +++++++++++++++++----- SRC/Core/Gekko.h | 4 +++- SRC/Core/Jitc.cpp | 5 +++++ SRC/Core/Jitc.h | 1 + SRC/Core/JitcX64/Fallback.cpp | 2 +- SRC/DSP/DspCore.cpp | 28 ++++++++++++++-------------- SRC/DSP/DspCore.h | 12 ++++++------ SRC/Debugger/input.cpp | 3 ++- SRC/Hardware/AI.cpp | 4 ++++ SRC/Hardware/AI.h | 7 +++++-- 10 files changed, 58 insertions(+), 30 deletions(-) diff --git a/SRC/Core/Gekko.cpp b/SRC/Core/Gekko.cpp index d9d54321..58d6dadb 100644 --- a/SRC/Core/Gekko.cpp +++ b/SRC/Core/Gekko.cpp @@ -262,11 +262,6 @@ namespace Gekko interp->ExecuteOpcodeDirect(pc, instr); } - bool __fastcall GekkoCore::ExecuteInterpeterFallback() - { - return Gekko->interp->ExecuteInterpeterFallback(); - } - uint32_t GekkoCore::EffectiveToPhysical(uint32_t ea, MmuAccess type, int& WIMG) { //return EffectiveToPhysicalNoMmu(ea, type, WIMG); @@ -315,6 +310,12 @@ namespace Gekko if (!EnableTestBreakpoints) return false; + if (oneShotBreakpoint != BadAddress && regs.pc == oneShotBreakpoint) + { + oneShotBreakpoint = BadAddress; + return true; + } + bool exists = false; breakPointsLock.Lock(); @@ -336,6 +337,12 @@ namespace Gekko if (!EnableTestBreakpoints) return; + if (oneShotBreakpoint != BadAddress && regs.pc == oneShotBreakpoint) + { + oneShotBreakpoint = BadAddress; + DBHalt("One shot breakpoint\n"); + } + uint32_t addr = BadAddress; breakPointsLock.Lock(); @@ -403,4 +410,9 @@ namespace Gekko } } + void GekkoCore::AddOneShotBreakpoint(uint32_t addr) + { + oneShotBreakpoint = addr; + } + } diff --git a/SRC/Core/Gekko.h b/SRC/Core/Gekko.h index 34932a4b..bb2efacd 100644 --- a/SRC/Core/Gekko.h +++ b/SRC/Core/Gekko.h @@ -97,6 +97,7 @@ namespace Gekko std::vector breakPointsRead; std::vector breakPointsWrite; SpinLock breakPointsLock; + uint32_t oneShotBreakpoint = BadAddress; bool TestBreakpointForJitc(uint32_t addr); void TestBreakpoints(); @@ -172,7 +173,6 @@ namespace Gekko size_t GetOpcodeCount() { return ops; } void ResetOpcodeCount() { ops = 0; } - static bool ExecuteInterpeterFallback(); void ExecuteOpcodeDebug(uint32_t pc, uint32_t instr); #pragma region "Memory interface" @@ -203,6 +203,8 @@ namespace Gekko void AddWriteBreak(uint32_t addr); void ClearBreakpoints(); + void AddOneShotBreakpoint(uint32_t addr); + #pragma endregion "Breakpoints" }; diff --git a/SRC/Core/Jitc.cpp b/SRC/Core/Jitc.cpp index 6933f279..d3a07ae5 100644 --- a/SRC/Core/Jitc.cpp +++ b/SRC/Core/Jitc.cpp @@ -195,6 +195,11 @@ namespace Gekko core->exception = false; } + bool Jitc::ExecuteInterpeterFallback() + { + return Gekko->interp->ExecuteInterpeterFallback(); + } + void Jitc::Reset() { InvalidateAll(); diff --git a/SRC/Core/Jitc.h b/SRC/Core/Jitc.h index af833e12..9caa33a0 100644 --- a/SRC/Core/Jitc.h +++ b/SRC/Core/Jitc.h @@ -78,6 +78,7 @@ namespace Gekko static void __fastcall ReadDouble(uint32_t addr, uint64_t* reg) { Gekko->ReadDouble(addr, reg); } static void __fastcall WriteDouble(uint32_t addr, uint64_t* data) { Gekko->WriteDouble(addr, data); } + static bool ExecuteInterpeterFallback(); static void Tick(); // This segment is not involved in invalidation, so as not to disrupt the code. diff --git a/SRC/Core/JitcX64/Fallback.cpp b/SRC/Core/JitcX64/Fallback.cpp index 71dea438..b27c32d0 100644 --- a/SRC/Core/JitcX64/Fallback.cpp +++ b/SRC/Core/JitcX64/Fallback.cpp @@ -13,7 +13,7 @@ namespace Gekko //7: 12 00 00 //17: ff d0 call rax - uint64_t fnPtr = (uint64_t)GekkoCore::ExecuteInterpeterFallback; + uint64_t fnPtr = (uint64_t)Jitc::ExecuteInterpeterFallback; seg->Write16(0xb848); seg->Write64(fnPtr); diff --git a/SRC/DSP/DspCore.cpp b/SRC/DSP/DspCore.cpp index 5f54fa42..b87f2366 100644 --- a/SRC/DSP/DspCore.cpp +++ b/SRC/DSP/DspCore.cpp @@ -99,7 +99,7 @@ namespace DSP { regs.ar[i] = 0; regs.ix[i] = 0; - regs.gpr[i] = 0; + regs.lm[i] = 0; } for (int i = 0; i < 2; i++) @@ -304,9 +304,9 @@ namespace DSP for (int i = 0; i < 4; i++) { - if (regs.gpr[i] != prevState->gpr[i]) + if (regs.lm[i] != prevState->lm[i]) { - DBReport("r%i: 0x%04X\n", 8+i, regs.gpr[i]); + DBReport("lm%i: 0x%04X\n", 8+i, regs.lm[i]); } } } @@ -343,11 +343,11 @@ namespace DSP case (int)DspRegister::ix3: regs.ix[reg - (int)DspRegister::indexRegs] = val; break; - case (int)DspRegister::r8: - case (int)DspRegister::r9: - case (int)DspRegister::r10: - case (int)DspRegister::r11: - regs.gpr[reg - (int)DspRegister::gprs] = val; + case (int)DspRegister::lm0: + case (int)DspRegister::lm1: + case (int)DspRegister::lm2: + case (int)DspRegister::lm3: + regs.lm[reg - (int)DspRegister::limitRegs] = val; break; case (int)DspRegister::st0: case (int)DspRegister::st1: @@ -428,11 +428,11 @@ namespace DSP case (int)DspRegister::ix2: case (int)DspRegister::ix3: return regs.ix[reg - (int)DspRegister::indexRegs]; - case (int)DspRegister::r8: - case (int)DspRegister::r9: - case (int)DspRegister::r10: - case (int)DspRegister::r11: - return regs.gpr[reg - (int)DspRegister::gprs]; + case (int)DspRegister::lm0: + case (int)DspRegister::lm1: + case (int)DspRegister::lm2: + case (int)DspRegister::lm3: + return regs.lm[reg - (int)DspRegister::limitRegs]; case (int)DspRegister::st0: case (int)DspRegister::st1: case (int)DspRegister::st2: @@ -574,7 +574,7 @@ namespace DSP return DspToCpuReadLo(true); case (DspAddress)DspHardwareRegs::DIRQ: - return 0; + return DSPGetInterruptStatus() ? 1 : 0; case (DspAddress)DspHardwareRegs::ACSAH: return Accel.StartAddress.h; diff --git a/SRC/DSP/DspCore.h b/SRC/DSP/DspCore.h index 5c70beb9..760a2e8d 100644 --- a/SRC/DSP/DspCore.h +++ b/SRC/DSP/DspCore.h @@ -100,11 +100,11 @@ namespace DSP ix1, // Indexing register 1 ix2, // Indexing register 2 ix3, // Indexing register 3 - gprs, - r8 = gprs, - r9, - r10, - r11, + limitRegs, + lm0 = limitRegs, + lm1, + lm2, + lm3, stackRegs, st0 = stackRegs, // Call stack register st1, // Data stack register @@ -133,7 +133,7 @@ namespace DSP uint32_t clearingPaddy; // To use {0} on structure uint16_t ar[4]; // Addressing registers uint16_t ix[4]; // Indexing registers - uint16_t gpr[4]; // General purpose (r8-r11) + uint16_t lm[4]; // Limit registers std::vector st[4]; // Stack registers DspLongAccumulator ac[2]; // 40-bit Accumulators DspShortAccumulator ax[2]; // 32-bit Accumulators diff --git a/SRC/Debugger/input.cpp b/SRC/Debugger/input.cpp index ff786790..380c49e3 100644 --- a/SRC/Debugger/input.cpp +++ b/SRC/Debugger/input.cpp @@ -80,7 +80,8 @@ static void con_function_key(int vkey, int ctrl) con.update |= CON_UPDATE_DISA; break; case VK_F10: // Step Over - // TODO: con_step_over(); + Gekko::Gekko->AddOneShotBreakpoint(Gekko::Gekko->regs.pc + 4); + Gekko::Gekko->Run(); break; case VK_F11: // Step Into con_step_into(); diff --git a/SRC/Hardware/AI.cpp b/SRC/Hardware/AI.cpp index 3afa8bd5..2341fbd0 100644 --- a/SRC/Hardware/AI.cpp +++ b/SRC/Hardware/AI.cpp @@ -381,6 +381,10 @@ void DSPAssertInt() } } +bool DSPGetInterruptStatus() +{ + return (AIDCR & AIDCR_DSPINT) != 0; +} // --------------------------------------------------------------------------- diff --git a/SRC/Hardware/AI.h b/SRC/Hardware/AI.h index c9e7df3c..d5b60ba2 100644 --- a/SRC/Hardware/AI.h +++ b/SRC/Hardware/AI.h @@ -26,7 +26,7 @@ #define AIDCR_AIINTMSK (1 << 4) // AI DMA interrupt mask (RW) #define AIDCR_AIINT (1 << 3) // AI DMA interrupt status (RWC) #define AIDCR_HALT (1 << 2) // halt DSP (stop ucoding) -#define AIDCR_DINT (1 << 1) // assert *DSP* interrupt +#define AIDCR_DINT (1 << 1) // CPU->DSP interrupt #define AIDCR_RES (1 << 0) // reset DSP (waits for 0) // enable bit in AIDLEN register @@ -89,4 +89,7 @@ extern AIControl ai; void AIOpen(HWConfig * config); void AIClose(); -void DSPAssertInt(); // Used by DspCore +// Used by DspCore + +void DSPAssertInt(); +bool DSPGetInterruptStatus(); From 195d55c96be14730291a2f3c1024f88df9f22001 Mon Sep 17 00:00:00 2001 From: ogamespec Date: Tue, 5 May 2020 03:10:33 +0300 Subject: [PATCH 4/9] Update DspCommands.cpp --- SRC/DSP/DspCommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SRC/DSP/DspCommands.cpp b/SRC/DSP/DspCommands.cpp index 9c7c928a..3b2f7ec7 100644 --- a/SRC/DSP/DspCommands.cpp +++ b/SRC/DSP/DspCommands.cpp @@ -96,7 +96,7 @@ namespace DSP { regsChanged.ar[i] = ~regsChanged.ar[i]; regsChanged.ix[i] = ~regsChanged.ix[i]; - regsChanged.gpr[i] = ~regsChanged.gpr[i]; + regsChanged.lm[i] = ~regsChanged.lm[i]; } for (int i = 0; i < 2; i++) From b6c1ba184f54d7c7b3bc9c37d38cfca15cfec2ef Mon Sep 17 00:00:00 2001 From: ogamespec Date: Tue, 5 May 2020 03:17:35 +0300 Subject: [PATCH 5/9] Dsp Limit regs --- Docs/RE/dsp_ucodes/JAudio_NTSC10_IPL.md | 18 +++++++++--------- Docs/RE/dsp_ucodes/dspirom_disa.md | 6 +++--- SRC/DSP/DspAnalyzer.h | 8 ++++---- SRC/DSP/DspDisasm.cpp | 8 ++++---- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Docs/RE/dsp_ucodes/JAudio_NTSC10_IPL.md b/Docs/RE/dsp_ucodes/JAudio_NTSC10_IPL.md index 572e8244..ae1dc9ba 100644 --- a/Docs/RE/dsp_ucodes/JAudio_NTSC10_IPL.md +++ b/Docs/RE/dsp_ucodes/JAudio_NTSC10_IPL.md @@ -46,10 +46,10 @@ All interrupt handlers except #0 are stubs. 0016 8C 00 clr15 0017 8B 00 m0 0018 00 9E FF FF lri ac0.m, #0xFFFF -001A 1D 1E mrr r08, ac0.m -001B 1D 3E mrr r09, ac0.m -001C 1D 5E mrr r0a, ac0.m -001D 1D 7E mrr r0b, ac0.m +001A 1D 1E mrr lm0, ac0.m +001B 1D 3E mrr lm1, ac0.m +001C 1D 5E mrr lm2, ac0.m +001D 1D 7E mrr lm3, ac0.m 001E 00 92 00 FF lri bank, #0x00FF 0020 81 00 clr ac0 0021 00 9F 10 00 lri ac1.m, #0x1000 @@ -77,7 +77,7 @@ Start() // 0010 clr15(); m0(); - r8 = r9 = r10 = r11 = 0xFFFF; + lm0 = lm1 = lm2 = lm3 = 0xFFFF; bank = 0xFF; // BankReg at 0xFF00 (IFX) // Clear DRAM (8 KBytes) @@ -547,7 +547,7 @@ Wait until Dsp Dma completed. 01B9 1C 1F mrr ar0, ac1.m 01BA 02 9F 01 9F j $0x019F 01BC 8A 00 m2 -01BD 00 88 00 07 lri r08, #0x0007 +01BD 00 88 00 07 lri lm0, #0x0007 01BF 11 50 01 CC bloopi #0x50, $0x01CC 01C1 1C 61 mrr ar3, ar1 01C2 84 C3 clrp ldax ax0, @ar0 @@ -561,13 +561,13 @@ Wait until Dsp Dma completed. 01CA F2 00 madd ax0.l, ax0.h 01CB FE 00 movpz ac0 01CC 1B 3E srri @ar1, ac0.m -01CD 00 88 FF FF lri r08, #0xFFFF +01CD 00 88 FF FF lri lm0, #0xFFFF 01CF 8B 00 m0 01D0 02 DF ret -01D1 00 88 00 03 lri r08, #0x0003 +01D1 00 88 00 03 lri lm0, #0x0003 01D3 00 85 00 00 lri ix1, #0x0000 01D5 00 87 00 00 lri ix3, #0x0000 01D7 1F C2 mrr ac0.m, ar2 @@ -606,7 +606,7 @@ Wait until Dsp Dma completed. 01F9 19 7F lrri ac1.m, @ar3 01FA 8E 00 clr40 01FB 8B 00 m0 -01FC 00 88 FF FF lri r08, #0xFFFF +01FC 00 88 FF FF lri lm0, #0xFFFF 01FE 1B 5B srri @ar2, ax1.h 01FF 1B 59 srri @ar2, ax0.h 0200 1B 5F srri @ar2, ac1.m diff --git a/Docs/RE/dsp_ucodes/dspirom_disa.md b/Docs/RE/dsp_ucodes/dspirom_disa.md index c989baf6..ded028d7 100644 --- a/Docs/RE/dsp_ucodes/dspirom_disa.md +++ b/Docs/RE/dsp_ucodes/dspirom_disa.md @@ -1786,7 +1786,7 @@ Called from IPL, CardUnlock 86B4 00 82 04 0E lri ar2, #0x040E 86B6 00 85 04 10 lri ix1, #0x0410 86B8 00 87 FF FE lri ix3, #0xFFFE -86BA 00 88 04 0E lri r08, #0x040E +86BA 00 88 04 0E lri lm0, #0x040E 86BC 00 DF 04 03 lr ac1.m, $0x0403 86BE 79 00 decm ac1 86BF 15 7F lsr ac1, #0x3F @@ -1805,7 +1805,7 @@ Called from IPL, CardUnlock 86CF 1C 65 mrr ar3, ix1 86D0 02 9D 86 D4 jok $0x86D4 86D2 02 BF 86 E5 call $0x86E5 -86D4 00 88 FF FF lri r08, #0xFFFF +86D4 00 88 FF FF lri lm0, #0xFFFF 86D6 16 C9 00 01 si $(DSCR), #0x0001 86D8 00 DE 04 06 lr ac0.m, $0x0406 86DA 2E CE srs $(DSMAH), ac0.m @@ -1854,7 +1854,7 @@ Called from IPL, CardUnlock 8705 04 28 addis ac0.m, 40 8706 6C 1E mov ac0, ac1 mv ax1.h, ac0.m 8707 14 08 lsl ac0, #0x08 -8708 1C 68 mrr ar3, r08 +8708 1C 68 mrr ar3, lm0 8709 34 86 andr ac0.m, ax0.h sln ac0.m, ax0.l 870A 37 86 andr ac1.m, ax1.h sln ac0.m, ax0.l 870B 4C 52 add ac0, ac1 l ax1.l, @ar2 diff --git a/SRC/DSP/DspAnalyzer.h b/SRC/DSP/DspAnalyzer.h index e950d0be..46d2653b 100644 --- a/SRC/DSP/DspAnalyzer.h +++ b/SRC/DSP/DspAnalyzer.h @@ -219,10 +219,10 @@ namespace DSP ix1, ///< Indexing register 1 ix2, ///< Indexing register 2 ix3, ///< Indexing register 3 - r08, - r09, - r0a, - r0b, + lm0, + lm1, + lm2, + lm3, st0, ///< Call stack register st1, ///< Data stack register st2, ///< Loop address stack register diff --git a/SRC/DSP/DspDisasm.cpp b/SRC/DSP/DspDisasm.cpp index 6ffa9692..217bd121 100644 --- a/SRC/DSP/DspDisasm.cpp +++ b/SRC/DSP/DspDisasm.cpp @@ -20,10 +20,10 @@ namespace DSP case DspParameter::ix1: text = "ix1"; break; case DspParameter::ix2: text = "ix2"; break; case DspParameter::ix3: text = "ix3"; break; - case DspParameter::r08: text = "r08"; break; - case DspParameter::r09: text = "r09"; break; - case DspParameter::r0a: text = "r0a"; break; - case DspParameter::r0b: text = "r0b"; break; + case DspParameter::lm0: text = "lm0"; break; + case DspParameter::lm1: text = "lm1"; break; + case DspParameter::lm2: text = "lm2"; break; + case DspParameter::lm3: text = "lm3"; break; case DspParameter::st0: text = "st0"; break; case DspParameter::st1: text = "st1"; break; case DspParameter::st2: text = "st2"; break; From b13615ba0476ceea69b44984b9d5b63329394c2c Mon Sep 17 00:00:00 2001 From: ogamespec Date: Tue, 5 May 2020 13:05:14 +0300 Subject: [PATCH 6/9] Gekko breakpoints in debugger by F9 key functional again --- SRC/Core/Breakpoints.cpp | 220 +++++++++++++++++++++ SRC/Core/Gekko.cpp | 147 -------------- SRC/Core/Gekko.h | 12 +- SRC/Core/Scripts/GekkoCore.vcxproj | 1 + SRC/Core/Scripts/GekkoCore.vcxproj.filters | 3 + SRC/DSP/DspInterpreter.cpp | 5 + SRC/DSP/DspInterpreter.h | 1 + SRC/Debugger/cpuview.cpp | 3 +- SRC/Debugger/input.cpp | 6 +- 9 files changed, 240 insertions(+), 158 deletions(-) create mode 100644 SRC/Core/Breakpoints.cpp diff --git a/SRC/Core/Breakpoints.cpp b/SRC/Core/Breakpoints.cpp new file mode 100644 index 00000000..de537b75 --- /dev/null +++ b/SRC/Core/Breakpoints.cpp @@ -0,0 +1,220 @@ +// Support for breakpoints. + +// After switching the Gekko emulation as a separate thread, the implementation of breakpoints is trivial. +// When a breakpoint occurs, we just do Suspend of the Gekko thread. +// And since all the other subsystems are tied to the Gekko thread (except for the UI and Debugger, it has an independent thread) +// the whole system stops with the processor. + +#include "pch.h" + +namespace Gekko +{ + void GekkoCore::AddBreakpoint(uint32_t addr) + { + breakPointsLock.Lock(); + bool exists = false; + for (auto it = breakPointsExecute.begin(); it != breakPointsExecute.end(); ++it) + { + if (*it == addr) + { + exists = true; + break; + } + } + if (!exists) + { + DBReport2(DbgChannel::CPU, "Breakpoint added: 0x%08X\n", addr); + breakPointsExecute.push_back(addr); + jitc->Invalidate(addr, 4); + EnableTestBreakpoints = true; + } + breakPointsLock.Unlock(); + } + + void GekkoCore::RemoveBreakpoint(uint32_t addr) + { + breakPointsLock.Lock(); + bool exists = false; + for (auto it = breakPointsExecute.begin(); it != breakPointsExecute.end(); ++it) + { + if (*it == addr) + { + exists = true; + break; + } + } + if (exists) + { + DBReport2(DbgChannel::CPU, "Breakpoint removed: 0x%08X\n", addr); + breakPointsExecute.remove(addr); + jitc->Invalidate(addr, 4); + } + if (breakPointsExecute.size() == 0) + { + EnableTestBreakpoints = false; + } + breakPointsLock.Unlock(); + } + + void GekkoCore::AddReadBreak(uint32_t addr) + { + breakPointsLock.Lock(); + breakPointsRead.push_back(addr); + breakPointsLock.Unlock(); + EnableTestReadBreakpoints = true; + } + + void GekkoCore::AddWriteBreak(uint32_t addr) + { + breakPointsLock.Lock(); + breakPointsWrite.push_back(addr); + breakPointsLock.Unlock(); + EnableTestWriteBreakpoints = true; + } + + void GekkoCore::ClearBreakpoints() + { + breakPointsLock.Lock(); + breakPointsExecute.clear(); + breakPointsRead.clear(); + breakPointsWrite.clear(); + breakPointsLock.Unlock(); + EnableTestBreakpoints = false; + EnableTestReadBreakpoints = false; + EnableTestWriteBreakpoints = false; + } + + bool GekkoCore::TestBreakpointForJitc(uint32_t addr) + { + if (!EnableTestBreakpoints) + return false; + + if (oneShotBreakpoint != BadAddress && regs.pc == oneShotBreakpoint) + { + oneShotBreakpoint = BadAddress; + return true; + } + + bool exists = false; + + breakPointsLock.Lock(); + for (auto it = breakPointsExecute.begin(); it != breakPointsExecute.end(); ++it) + { + if (*it == addr) + { + exists = true; + break; + } + } + breakPointsLock.Unlock(); + + return exists; + } + + void GekkoCore::TestBreakpoints() + { + if (!EnableTestBreakpoints) + return; + + if (oneShotBreakpoint != BadAddress && regs.pc == oneShotBreakpoint) + { + oneShotBreakpoint = BadAddress; + DBHalt("One shot breakpoint\n"); + } + + uint32_t addr = BadAddress; + + breakPointsLock.Lock(); + for (auto it = breakPointsExecute.begin(); it != breakPointsExecute.end(); ++it) + { + if (*it == regs.pc) + { + addr = *it; + break; + } + } + breakPointsLock.Unlock(); + + if (addr != BadAddress) + { + DBHalt("Gekko suspended at addr: 0x%08X\n", addr); + } + } + + void GekkoCore::TestReadBreakpoints(uint32_t accessAddress) + { + if (!EnableTestReadBreakpoints) + return; + + uint32_t addr = BadAddress; + + breakPointsLock.Lock(); + for (auto it = breakPointsRead.begin(); it != breakPointsRead.end(); ++it) + { + if (*it == accessAddress) + { + addr = *it; + break; + } + } + breakPointsLock.Unlock(); + + if (addr != BadAddress) + { + DBHalt("Gekko suspended trying to read: 0x%08X\n", addr); + } + } + + void GekkoCore::TestWriteBreakpoints(uint32_t accessAddress) + { + if (!EnableTestWriteBreakpoints) + return; + + uint32_t addr = BadAddress; + + breakPointsLock.Lock(); + for (auto it = breakPointsWrite.begin(); it != breakPointsWrite.end(); ++it) + { + if (*it == accessAddress) + { + addr = *it; + break; + } + } + breakPointsLock.Unlock(); + + if (addr != BadAddress) + { + DBHalt("Gekko suspended trying to write: 0x%08X\n", addr); + } + } + + void GekkoCore::AddOneShotBreakpoint(uint32_t addr) + { + oneShotBreakpoint = addr; + } + + void GekkoCore::ToggleBreakpoint(uint32_t addr) + { + if (IsBreakpoint(addr)) + RemoveBreakpoint(addr); + else + AddBreakpoint(addr); + } + + bool GekkoCore::IsBreakpoint(uint32_t addr) + { + bool exists = false; + breakPointsLock.Lock(); + for (auto it = breakPointsExecute.begin(); it != breakPointsExecute.end(); ++it) + { + if (*it == addr) + { + exists = true; + break; + } + } + breakPointsLock.Unlock(); + return exists; + } +} diff --git a/SRC/Core/Gekko.cpp b/SRC/Core/Gekko.cpp index 58d6dadb..029123fb 100644 --- a/SRC/Core/Gekko.cpp +++ b/SRC/Core/Gekko.cpp @@ -268,151 +268,4 @@ namespace Gekko return EffectiveToPhysicalMmu(ea, type, WIMG); } - void GekkoCore::AddBreakpoint(uint32_t addr) - { - breakPointsLock.Lock(); - breakPointsExecute.push_back(addr); - jitc->Invalidate(addr, 4); - breakPointsLock.Unlock(); - EnableTestBreakpoints = true; - } - - void GekkoCore::AddReadBreak(uint32_t addr) - { - breakPointsLock.Lock(); - breakPointsRead.push_back(addr); - breakPointsLock.Unlock(); - EnableTestReadBreakpoints = true; - } - - void GekkoCore::AddWriteBreak(uint32_t addr) - { - breakPointsLock.Lock(); - breakPointsWrite.push_back(addr); - breakPointsLock.Unlock(); - EnableTestWriteBreakpoints = true; - } - - void GekkoCore::ClearBreakpoints() - { - breakPointsLock.Lock(); - breakPointsExecute.clear(); - breakPointsRead.clear(); - breakPointsWrite.clear(); - breakPointsLock.Unlock(); - EnableTestBreakpoints = false; - EnableTestReadBreakpoints = false; - EnableTestWriteBreakpoints = false; - } - - bool GekkoCore::TestBreakpointForJitc(uint32_t addr) - { - if (!EnableTestBreakpoints) - return false; - - if (oneShotBreakpoint != BadAddress && regs.pc == oneShotBreakpoint) - { - oneShotBreakpoint = BadAddress; - return true; - } - - bool exists = false; - - breakPointsLock.Lock(); - for (auto it = breakPointsExecute.begin(); it != breakPointsExecute.end(); ++it) - { - if (*it == addr) - { - exists = true; - break; - } - } - breakPointsLock.Unlock(); - - return exists; - } - - void GekkoCore::TestBreakpoints() - { - if (!EnableTestBreakpoints) - return; - - if (oneShotBreakpoint != BadAddress && regs.pc == oneShotBreakpoint) - { - oneShotBreakpoint = BadAddress; - DBHalt("One shot breakpoint\n"); - } - - uint32_t addr = BadAddress; - - breakPointsLock.Lock(); - for (auto it = breakPointsExecute.begin(); it != breakPointsExecute.end(); ++it) - { - if (*it == regs.pc) - { - addr = *it; - break; - } - } - breakPointsLock.Unlock(); - - if (addr != BadAddress) - { - DBHalt("Gekko suspended at addr: 0x%08X\n", addr); - } - } - - void GekkoCore::TestReadBreakpoints(uint32_t accessAddress) - { - if (!EnableTestReadBreakpoints) - return; - - uint32_t addr = BadAddress; - - breakPointsLock.Lock(); - for (auto it = breakPointsRead.begin(); it != breakPointsRead.end(); ++it) - { - if (*it == accessAddress) - { - addr = *it; - break; - } - } - breakPointsLock.Unlock(); - - if (addr != BadAddress) - { - DBHalt("Gekko suspended trying to read: 0x%08X\n", addr); - } - } - - void GekkoCore::TestWriteBreakpoints(uint32_t accessAddress) - { - if (!EnableTestWriteBreakpoints) - return; - - uint32_t addr = BadAddress; - - breakPointsLock.Lock(); - for (auto it = breakPointsWrite.begin(); it != breakPointsWrite.end(); ++it) - { - if (*it == accessAddress) - { - addr = *it; - break; - } - } - breakPointsLock.Unlock(); - - if (addr != BadAddress) - { - DBHalt("Gekko suspended trying to write: 0x%08X\n", addr); - } - } - - void GekkoCore::AddOneShotBreakpoint(uint32_t addr) - { - oneShotBreakpoint = addr; - } - } diff --git a/SRC/Core/Gekko.h b/SRC/Core/Gekko.h index bb2efacd..f6a784f9 100644 --- a/SRC/Core/Gekko.h +++ b/SRC/Core/Gekko.h @@ -3,7 +3,7 @@ #pragma once #include "../Common/Thread.h" -#include +#include #include "GekkoDefs.h" #include "GekkoAnalyzer.h" #include "GatherBuffer.h" @@ -93,9 +93,9 @@ namespace Gekko Thread* gekkoThread = nullptr; static void GekkoThreadProc(void* Parameter); - std::vector breakPointsExecute; - std::vector breakPointsRead; - std::vector breakPointsWrite; + std::list breakPointsExecute; + std::list breakPointsRead; + std::list breakPointsWrite; SpinLock breakPointsLock; uint32_t oneShotBreakpoint = BadAddress; @@ -199,12 +199,16 @@ namespace Gekko #pragma region "Breakpoints" void AddBreakpoint(uint32_t addr); + void RemoveBreakpoint(uint32_t addr); void AddReadBreak(uint32_t addr); void AddWriteBreak(uint32_t addr); void ClearBreakpoints(); void AddOneShotBreakpoint(uint32_t addr); + void ToggleBreakpoint(uint32_t addr); + bool IsBreakpoint(uint32_t addr); + #pragma endregion "Breakpoints" }; diff --git a/SRC/Core/Scripts/GekkoCore.vcxproj b/SRC/Core/Scripts/GekkoCore.vcxproj index f6e94808..6d8d0c45 100644 --- a/SRC/Core/Scripts/GekkoCore.vcxproj +++ b/SRC/Core/Scripts/GekkoCore.vcxproj @@ -167,6 +167,7 @@ + diff --git a/SRC/Core/Scripts/GekkoCore.vcxproj.filters b/SRC/Core/Scripts/GekkoCore.vcxproj.filters index 26c59a47..d498c999 100644 --- a/SRC/Core/Scripts/GekkoCore.vcxproj.filters +++ b/SRC/Core/Scripts/GekkoCore.vcxproj.filters @@ -167,6 +167,9 @@ JitcX64 + + Source Files + diff --git a/SRC/DSP/DspInterpreter.cpp b/SRC/DSP/DspInterpreter.cpp index 6f753bae..b3f5c4b9 100644 --- a/SRC/DSP/DspInterpreter.cpp +++ b/SRC/DSP/DspInterpreter.cpp @@ -1195,6 +1195,11 @@ namespace DSP Flags40(SignExtend40(a.bits), SignExtend40(b.bits), SignExtend40(res.bits)); } + void DspInterpreter::FlagsLogic(DspLongAccumulator a) + { + + } + void DspInterpreter::SetLoop(DspAddress startAddr, DspAddress endAddr, uint16_t count) { core->regs.st[0].push_back(startAddr); diff --git a/SRC/DSP/DspInterpreter.h b/SRC/DSP/DspInterpreter.h index f7306e0f..aaa1a629 100644 --- a/SRC/DSP/DspInterpreter.h +++ b/SRC/DSP/DspInterpreter.h @@ -184,6 +184,7 @@ namespace DSP bool Condition(ConditionCode cc); void Flags40(int64_t a, int64_t b, int64_t res); void Flags(DspLongAccumulator a, DspLongAccumulator b, DspLongAccumulator res); + void FlagsLogic(DspLongAccumulator a); void Dispatch(AnalyzeInfo& info); void SetLoop(DspAddress startAddr, DspAddress endAddr, uint16_t count); bool CheckLoop(); diff --git a/SRC/Debugger/cpuview.cpp b/SRC/Debugger/cpuview.cpp index 78d75c36..25e4a1ea 100644 --- a/SRC/Debugger/cpuview.cpp +++ b/SRC/Debugger/cpuview.cpp @@ -8,8 +8,7 @@ static int con_disa_line(int line, uint32_t opcode, uint32_t addr) int addend = 1; bgcur = (addr == con.disa_cursor) ? (8) : (0); - //bgbp = (con_is_code_bp(addr)) ? (4) : (0); - bgbp = 0; + bgbp = (Gekko::Gekko->IsBreakpoint(addr)) ? (4) : (0); bg = (addr == Gekko::Gekko->regs.pc) ? (1) : (0); bg = bg ^ bgcur ^ bgbp; fg = 7; diff --git a/SRC/Debugger/input.cpp b/SRC/Debugger/input.cpp index 380c49e3..24537bc4 100644 --- a/SRC/Debugger/input.cpp +++ b/SRC/Debugger/input.cpp @@ -72,11 +72,7 @@ static void con_function_key(int vkey, int ctrl) } break; case VK_F9: // Toggle Breakpoint - //if(con_is_code_bp(con.disa_cursor)) - //{ - // con_rem_code_bp(con.disa_cursor); - //} - //else con_add_code_bp(con.disa_cursor); + Gekko::Gekko->ToggleBreakpoint(con.disa_cursor); con.update |= CON_UPDATE_DISA; break; case VK_F10: // Step Over From f7580b5df630fba2e85777eaadc36ea4b929baf6 Mon Sep 17 00:00:00 2001 From: ogamespec Date: Tue, 5 May 2020 13:10:37 +0300 Subject: [PATCH 7/9] CacheDebugDisable command --- Data/GekkoCoreJdi.json | 9 +++++++++ SRC/Core/Cache.h | 12 ++++++++++++ SRC/Core/GekkoCommands.cpp | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/Data/GekkoCoreJdi.json b/Data/GekkoCoreJdi.json index d2743e08..cd672d39 100644 --- a/Data/GekkoCoreJdi.json +++ b/Data/GekkoCoreJdi.json @@ -71,6 +71,15 @@ "1: Show commands (cache control instructions activity)", "2: Show all operations (load/store, cast-in/cast-out, etc.)" ] + }, + + "CacheDebugDisable": { + "help": "Disable cache emulation despite Gekko register settings", + "args": 1, + "usage": [ + "Syntax: CacheDebugDisable <0|1>" + ] } + } } diff --git a/SRC/Core/Cache.h b/SRC/Core/Cache.h index 7146186f..46a14a58 100644 --- a/SRC/Core/Cache.h +++ b/SRC/Core/Cache.h @@ -81,5 +81,17 @@ namespace Gekko void LockedCacheDma(bool MemToCache, uint32_t memaddr, uint32_t lcaddr, size_t bursts); void SetLogLevel(CacheLogLevel level) { log = level; } + void DebugDisable(bool disable) + { + if (disable) + { + DBReport2(DbgChannel::CPU, "Cache disabled for debug purposes"); + } + else + { + DBReport2(DbgChannel::CPU, "Cache works normally"); + } + DisableForDebugReasons = disable; + } }; } diff --git a/SRC/Core/GekkoCommands.cpp b/SRC/Core/GekkoCommands.cpp index 0434838e..7b9a1dc5 100644 --- a/SRC/Core/GekkoCommands.cpp +++ b/SRC/Core/GekkoCommands.cpp @@ -356,6 +356,13 @@ namespace Gekko return nullptr; } + static Json::Value* CacheDebugDisable(std::vector& args) + { + bool disable = atoi(args[1].c_str()) ? true : false; + Gekko->cache.DebugDisable(disable); + return nullptr; + } + void gekko_init_handlers() { Debug::Hub.AddCmd("run", cmd_run); @@ -366,5 +373,6 @@ namespace Gekko Debug::Hub.AddCmd("bw", cmd_bw); Debug::Hub.AddCmd("bc", cmd_bc); Debug::Hub.AddCmd("CacheLog", CacheLog); + Debug::Hub.AddCmd("CacheDebugDisable", CacheDebugDisable); } } From 4a5e579dd27920ce22bb0b87e832c221774d395f Mon Sep 17 00:00:00 2001 From: ogamespec Date: Tue, 5 May 2020 13:38:27 +0300 Subject: [PATCH 8/9] TLB support enabled --- Data/DefaultSettings.json | 14 +------------- Data/{ => Json}/DduJdi.json | 0 Data/{ => Json}/DebuggerJdi.json | 0 Data/{ => Json}/DolphinSdkDvdData.json | 0 Data/{ => Json}/DspJdi.json | 0 Data/{ => Json}/EmuJdi.json | 0 Data/{ => Json}/GekkoCoreJdi.json | 0 Data/{ => Json}/HLEJdi.json | 0 Data/{ => Json}/HWJdi.json | 0 Data/Json/Readme.md | 3 +++ SRC/Core/Cache.h | 2 +- SRC/Core/Gekko.cpp | 3 ++- SRC/Core/Gekko.h | 3 ++- SRC/Core/GekkoCommands.h | 2 +- SRC/Core/Interpreter/System.cpp | 3 ++- SRC/Core/Mmu.cpp | 16 ++++++++++++++++ SRC/Core/TLB.cpp | 18 ++++++++++++++---- SRC/Core/TLB.h | 12 +++++++++--- SRC/DSP/DspCommands.h | 2 +- SRC/DVD/DduCommands.h | 2 +- SRC/DVD/MountSDK.h | 2 +- SRC/Debugger/DebugCommands.h | 2 +- SRC/Dolwin/EmuCommands.h | 2 +- SRC/Hardware/HwCommands.h | 2 +- SRC/HighLevel/HleCommands.h | 2 +- 25 files changed, 58 insertions(+), 32 deletions(-) rename Data/{ => Json}/DduJdi.json (100%) rename Data/{ => Json}/DebuggerJdi.json (100%) rename Data/{ => Json}/DolphinSdkDvdData.json (100%) rename Data/{ => Json}/DspJdi.json (100%) rename Data/{ => Json}/EmuJdi.json (100%) rename Data/{ => Json}/GekkoCoreJdi.json (100%) rename Data/{ => Json}/HLEJdi.json (100%) rename Data/{ => Json}/HWJdi.json (100%) create mode 100644 Data/Json/Readme.md diff --git a/Data/DefaultSettings.json b/Data/DefaultSettings.json index 95eab7d3..658d19c7 100644 --- a/Data/DefaultSettings.json +++ b/Data/DefaultSettings.json @@ -72,18 +72,6 @@ "Memcard_SyncSave": false, "MemcardA_Connected": false, "MemcardB_Connected": false - }, - - "testing": - { - "SomeUTF8String": "Я могу есть стекло, оно мне не вредит", - "Japan": "私はガラスを食べることができます、それは私に害を与えません", - "Arabic": "يمكنني أكل الزجاج ، لا يؤذيني ", - "English": "I can eat glass, it doesn't hurts me", - "Boolean": true, - "Float": 3.1415, - "SomeArray": [ 1, 2, 3], - "EmptyArray": [], - "EmptyObject": {} } + } diff --git a/Data/DduJdi.json b/Data/Json/DduJdi.json similarity index 100% rename from Data/DduJdi.json rename to Data/Json/DduJdi.json diff --git a/Data/DebuggerJdi.json b/Data/Json/DebuggerJdi.json similarity index 100% rename from Data/DebuggerJdi.json rename to Data/Json/DebuggerJdi.json diff --git a/Data/DolphinSdkDvdData.json b/Data/Json/DolphinSdkDvdData.json similarity index 100% rename from Data/DolphinSdkDvdData.json rename to Data/Json/DolphinSdkDvdData.json diff --git a/Data/DspJdi.json b/Data/Json/DspJdi.json similarity index 100% rename from Data/DspJdi.json rename to Data/Json/DspJdi.json diff --git a/Data/EmuJdi.json b/Data/Json/EmuJdi.json similarity index 100% rename from Data/EmuJdi.json rename to Data/Json/EmuJdi.json diff --git a/Data/GekkoCoreJdi.json b/Data/Json/GekkoCoreJdi.json similarity index 100% rename from Data/GekkoCoreJdi.json rename to Data/Json/GekkoCoreJdi.json diff --git a/Data/HLEJdi.json b/Data/Json/HLEJdi.json similarity index 100% rename from Data/HLEJdi.json rename to Data/Json/HLEJdi.json diff --git a/Data/HWJdi.json b/Data/Json/HWJdi.json similarity index 100% rename from Data/HWJdi.json rename to Data/Json/HWJdi.json diff --git a/Data/Json/Readme.md b/Data/Json/Readme.md new file mode 100644 index 00000000..2e7e61d7 --- /dev/null +++ b/Data/Json/Readme.md @@ -0,0 +1,3 @@ +# Json + +In this folder are auxiliary Json, mainly those related to the service and debugging interface (Jdi). diff --git a/SRC/Core/Cache.h b/SRC/Core/Cache.h index 46a14a58..4bb9ca11 100644 --- a/SRC/Core/Cache.h +++ b/SRC/Core/Cache.h @@ -38,7 +38,7 @@ namespace Gekko // You can disable cache emulation for debugging purposes. // This does not apply to a locked cache. - bool DisableForDebugReasons = false; + bool DisableForDebugReasons = true; uint8_t* LockedCache = nullptr; uint32_t LockedCacheAddr = 0; diff --git a/SRC/Core/Gekko.cpp b/SRC/Core/Gekko.cpp index 029123fb..e57413dd 100644 --- a/SRC/Core/Gekko.cpp +++ b/SRC/Core/Gekko.cpp @@ -99,7 +99,8 @@ namespace Gekko jitc->Reset(); segmentsExecuted = 0; - tlb.InvalidateAll(); + dtlb.InvalidateAll(); + itlb.InvalidateAll(); cache.Reset(); } diff --git a/SRC/Core/Gekko.h b/SRC/Core/Gekko.h index f6a784f9..db05ba0f 100644 --- a/SRC/Core/Gekko.h +++ b/SRC/Core/Gekko.h @@ -134,7 +134,8 @@ namespace Gekko bool __fastcall BlockAddressTranslation(uint32_t ea, uint32_t& pa, MmuAccess type, int& WIMG); uint32_t __fastcall SegmentTranslation(uint32_t ea, MmuAccess type, int& WIMG); - TLB tlb; + TLB dtlb; + TLB itlb; PrivilegedCause PrCause; diff --git a/SRC/Core/GekkoCommands.h b/SRC/Core/GekkoCommands.h index 3e596271..6cc73d70 100644 --- a/SRC/Core/GekkoCommands.h +++ b/SRC/Core/GekkoCommands.h @@ -2,7 +2,7 @@ #pragma once -#define GEKKO_CORE_JDI_JSON L"Data\\GekkoCoreJdi.json" +#define GEKKO_CORE_JDI_JSON L"Data\\Json\\GekkoCoreJdi.json" namespace Gekko { diff --git a/SRC/Core/Interpreter/System.cpp b/SRC/Core/Interpreter/System.cpp index 08cfc095..60b33096 100644 --- a/SRC/Core/Interpreter/System.cpp +++ b/SRC/Core/Interpreter/System.cpp @@ -412,7 +412,8 @@ namespace Gekko OP(TLBIE) { - Gekko->tlb.Invalidate(RRB); + Gekko->dtlb.Invalidate(RRB); + Gekko->itlb.Invalidate(RRB); Gekko->regs.pc += 4; } diff --git a/SRC/Core/Mmu.cpp b/SRC/Core/Mmu.cpp index d115aee6..eb30f73c 100644 --- a/SRC/Core/Mmu.cpp +++ b/SRC/Core/Mmu.cpp @@ -40,6 +40,15 @@ namespace Gekko WIMG = 0; + // Try TLB + + TLB* tlb = (type == MmuAccess::Execute) ? &itlb : &dtlb; + + if (tlb->Exists(ea, pa, WIMG)) + { + return pa; + } + // First, try the block translation, if it doesnt work, try the Page Table. if (!BlockAddressTranslation(ea, pa, type, WIMG)) @@ -47,6 +56,13 @@ namespace Gekko pa = SegmentTranslation(ea, type, WIMG); } + // Put in TLB + + if (MmuLastResult == MmuResult::Ok) + { + tlb->Map(ea, pa, WIMG); + } + return pa; } diff --git a/SRC/Core/TLB.cpp b/SRC/Core/TLB.cpp index 4ba019fa..676031c4 100644 --- a/SRC/Core/TLB.cpp +++ b/SRC/Core/TLB.cpp @@ -2,20 +2,25 @@ namespace Gekko { - bool TLB::Exists(uint32_t ea, uint32_t& pa) + bool TLB::Exists(uint32_t ea, uint32_t& pa, int &WIMG) { auto it = tlb.find(ea >> 12); if (it != tlb.end()) { - pa = ((uint32_t)it->second << 12) | (ea & 0xfff); + TLBEntry* entry = it->second; + pa = (entry->addressTag << 12) | (ea & 0xfff); + WIMG = entry->wimg; return true; } return false; } - void TLB::Map(uint32_t ea, uint32_t pa) + void TLB::Map(uint32_t ea, uint32_t pa, int WIMG) { - tlb[ea >> 12] = pa >> 12; + TLBEntry* entry = new TLBEntry; + entry->addressTag = pa >> 12; + entry->wimg = WIMG; + tlb[ea >> 12] = entry; } void TLB::Invalidate(uint32_t ea) @@ -23,12 +28,17 @@ namespace Gekko auto it = tlb.find(ea >> 12); if (it != tlb.end()) { + delete it->second; tlb.erase(it); } } void TLB::InvalidateAll() { + for (auto it = tlb.begin(); it != tlb.end(); ++it) + { + delete it->second; + } tlb.clear(); } } diff --git a/SRC/Core/TLB.h b/SRC/Core/TLB.h index 41ce3688..68288d5f 100644 --- a/SRC/Core/TLB.h +++ b/SRC/Core/TLB.h @@ -6,13 +6,19 @@ namespace Gekko { + typedef struct _TLBEntry + { + uint32_t addressTag; + int8_t wimg; + } TLBEntry; + class TLB { - std::unordered_map tlb; + std::unordered_map tlb; public: - bool Exists(uint32_t ea, uint32_t& pa); - void Map(uint32_t ea, uint32_t pa); + bool Exists(uint32_t ea, uint32_t& pa, int& WIMG); + void Map(uint32_t ea, uint32_t pa, int WIMG); void Invalidate(uint32_t ea); void InvalidateAll(); diff --git a/SRC/DSP/DspCommands.h b/SRC/DSP/DspCommands.h index 06760f1c..b80e7c07 100644 --- a/SRC/DSP/DspCommands.h +++ b/SRC/DSP/DspCommands.h @@ -2,7 +2,7 @@ #pragma once -#define DSP_JDI_JSON L"Data\\DspJdi.json" +#define DSP_JDI_JSON L"Data\\Json\\DspJdi.json" namespace DSP { diff --git a/SRC/DVD/DduCommands.h b/SRC/DVD/DduCommands.h index dd77e638..840ece55 100644 --- a/SRC/DVD/DduCommands.h +++ b/SRC/DVD/DduCommands.h @@ -2,7 +2,7 @@ #pragma once -#define DDU_JDI_JSON L"Data\\DduJdi.json" +#define DDU_JDI_JSON L"Data\\Json\\DduJdi.json" namespace DVD { diff --git a/SRC/DVD/MountSDK.h b/SRC/DVD/MountSDK.h index e23e7f2d..a9fb251a 100644 --- a/SRC/DVD/MountSDK.h +++ b/SRC/DVD/MountSDK.h @@ -17,7 +17,7 @@ namespace DVD TCHAR directory[0x1000] = { 0 }; Json DvdDataInfo; - const TCHAR* DvdDataJson = _T("Data\\DolphinSdkDvdData.json"); + const TCHAR* DvdDataJson = _T("Data\\Json\\DolphinSdkDvdData.json"); const TCHAR* AppldrPath = _T("/HW2/boot/apploader.img"); const TCHAR* Bi2Path = _T("/X86/bin/bi2.bin"); diff --git a/SRC/Debugger/DebugCommands.h b/SRC/Debugger/DebugCommands.h index fe699eef..8a51d4fe 100644 --- a/SRC/Debugger/DebugCommands.h +++ b/SRC/Debugger/DebugCommands.h @@ -2,7 +2,7 @@ #pragma once -#define DEBUGGER_JDI_JSON L"Data\\DebuggerJdi.json" +#define DEBUGGER_JDI_JSON L"Data\\Json\\DebuggerJdi.json" namespace Debug { diff --git a/SRC/Dolwin/EmuCommands.h b/SRC/Dolwin/EmuCommands.h index bb8f7e7f..415f2a6c 100644 --- a/SRC/Dolwin/EmuCommands.h +++ b/SRC/Dolwin/EmuCommands.h @@ -2,6 +2,6 @@ #pragma once -#define EMU_JDI_JSON L"Data\\EmuJdi.json" +#define EMU_JDI_JSON L"Data\\Json\\EmuJdi.json" void EmuReflector(); diff --git a/SRC/Hardware/HwCommands.h b/SRC/Hardware/HwCommands.h index ef5307f0..98d7d8a0 100644 --- a/SRC/Hardware/HwCommands.h +++ b/SRC/Hardware/HwCommands.h @@ -2,7 +2,7 @@ #pragma once -#define HW_JDI_JSON L"Data\\HWJdi.json" +#define HW_JDI_JSON L"Data\\Json\\HWJdi.json" namespace Flipper { diff --git a/SRC/HighLevel/HleCommands.h b/SRC/HighLevel/HleCommands.h index dbed4f65..6fc2dec2 100644 --- a/SRC/HighLevel/HleCommands.h +++ b/SRC/HighLevel/HleCommands.h @@ -2,7 +2,7 @@ #pragma once -#define HLE_JDI_JSON L"Data\\HLEJdi.json" +#define HLE_JDI_JSON L"Data\\Json\\HLEJdi.json" namespace HLE { From 848d38ead94ca0eac96cd41e40a86a5c077c050c Mon Sep 17 00:00:00 2001 From: ogamespec Date: Tue, 5 May 2020 14:05:00 +0300 Subject: [PATCH 9/9] Release notes 0.130 --- Docs/EMU/ReleaseNotes0130.md | 35 +++++++++++++++++++++++++++++++++ Docs/EMU/ReleaseNotes0130Rus.md | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 Docs/EMU/ReleaseNotes0130.md create mode 100644 Docs/EMU/ReleaseNotes0130Rus.md diff --git a/Docs/EMU/ReleaseNotes0130.md b/Docs/EMU/ReleaseNotes0130.md new file mode 100644 index 00000000..da622021 --- /dev/null +++ b/Docs/EMU/ReleaseNotes0130.md @@ -0,0 +1,35 @@ +# Dolwin 0.130 Release Notes + +The release with unlucky number 13 was split into two releases: 0.130 and 0.131. These superstitious programmers.. + +What's new: +- MMU support +- Support cache emulation +- Dynamic recompiler (JITC) +- Improved emulation of graphics FIFO +- Many other minor improvements + +All these things were added experimentally and at the moment the cache and recompiler are temporarily disabled. If you are a developer, you can rebuild Dolwin with the cache and recompiler turned on. + +The cache is enabled with the command `CacheDebugDisable 0`. + +The recompiler is turned on in SRC\\Core\\Gekko.cpp, line 20 (but the interpreter must be disabled). + +Between 0.130 and 0.131, I will try to fix all incomprehensible bugs with cache and recompiler so that they are included in the next release. + +## Requirements + +- Dolwin makes heavy use of multicore multithreading. Therefore, it is desirable that your processor contains 4 or more cores. +- The memory requirements are not so strict, a few gigabytes should be enough +- Emulation requires DSP IROM / DROM dumps +- A BIOS image dump is not required, but if you want to experiment with it, you can also add it in the settings. The BIOS is launched through the menu File -> Run Bootrom. Then you need to wait a bit and open the drive cover (File -> Swap Disk -> Open Cover). After that, IPL Menu will start :p + +## What happens + +Overall, the GameCube emulation has made significant progress. Games such as Ikaruga, 18 Wheeler, Super Monkey Ball, and for example Ed, Edd and Eddy are launched. + +However, not all of them reach Ingame, contain graphic bugs and suffer from lags. + +Most games still do not start due to insufficiently accurate emulation of the DSP or GPU. + +The next release (0.131) is aimed precisely at eliminating all the shortcomings of DSP emulation, so that at last you can launch such top games as Legend of Zelda. diff --git a/Docs/EMU/ReleaseNotes0130Rus.md b/Docs/EMU/ReleaseNotes0130Rus.md new file mode 100644 index 00000000..ff7ad9e1 --- /dev/null +++ b/Docs/EMU/ReleaseNotes0130Rus.md @@ -0,0 +1,35 @@ +# Заметки к релизу Dolwin 0.130 + +Релиз с несчастливым номером 13 был разбит на два релиза: 0.130 и 0.131. Ох уж эти суеверные программисты. + +Что нового: +- Поддержка MMU +- Поддержка эмуляции кэша +- Динамический рекомпилятор +- Улучшенная эмуляция графического FIFO +- Много других мелких улучшений + +Все эти вещи добавлены экспериментально и в настоящий момент кэш и рекомпилятор временно отключены. Если вы разработчик, то можете пересобрать Dolwin с включенным кэшем и рекомпилятором. + +Кэш включается командой `CacheDebugDisable 0`. + +Рекомпилятор включается в SRC\\Core\\Gekko.cpp, line 20 (но при этом нужно отключить интерпретатор). + +В промежутке между 0.130 и 0.131 я постараюсь исправить все непонятные баги с кэшем и рекомпилятором, чтобы они были включены в следующем релизе. + +## Требования + +- Dolwin интенсивно использует многоядерную многопоточность. Поэтому желательно чтобы ваш процессор содержал 4 или более ядер. +- Требования к памяти не такие жесткие, нескольких гигабайт должно хватить +- Для эмуляции требуются дампы DSP IROM/DROM +- Дамп образа BIOS не требуется, но если вы хотите с ним поэкспериментировать, то его можно тоже добавить в настройках. Запускается BIOS через меню File -> Run Bootrom. Затем нужно немного подождать и открыть крышку привода (File -> Swap Disk -> Open Cover). После этого запустится IPL Menu :p + +## Что получается + +В целом эмуляция GameCube значительно продвинулась вперед. Запускаются такие игры как Ikaruga, 18 Wheeler, Super Monkey Ball и например Ed, Edd and Eddy. + +Однако не все они доходят до Ingame, содержат графические баги и страдают тормозами. + +Большая часть игр по прежнему не запускается из-за недостаточно точной эмуляции DSP или графического процессора. + +Следующий релиз (0.131) нацелен как раз на устранение всех недочетов эмуляции DSP, чтобы наконец можно было запустить такие топовые игры как Legend of Zelda.