diff --git a/Common/LogManager.cpp b/Common/LogManager.cpp index 89539f57c1..d701750a0c 100644 --- a/Common/LogManager.cpp +++ b/Common/LogManager.cpp @@ -172,13 +172,11 @@ void LogManager::LoadConfig(IniFile::Section *section) { } void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const char *file, int line, const char *format, va_list args) { - std::lock_guard lk(log_lock_); - - char msg[MAX_MSGLEN * 2]; LogChannel *log = log_[type]; - if (!log || !log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners()) + if (level > log->GetLevel() || !log->IsEnabled() || !log->HasListeners()) return; + std::lock_guard lk(log_lock_); static const char level_to_char[8] = "-NEWIDV"; char formattedTime[13]; Common::Timer::GetTimeFormatted(formattedTime); @@ -196,7 +194,8 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const if (fileshort != file) file = fileshort + 1; } - + + char msg[MAX_MSGLEN * 2]; char *msgPos = msg; if (hleCurrentThreadName != NULL) { msgPos += sprintf(msgPos, "%s %-12.12s %c[%s]: %s:%d ", @@ -228,7 +227,7 @@ void LogManager::Shutdown() { } LogChannel::LogChannel(const char* shortName, const char* fullName, bool enable) - : enable_(enable) { + : enable_(enable), m_hasListeners(false) { strncpy(m_fullName, fullName, 128); strncpy(m_shortName, shortName, 32); #if defined(_DEBUG) @@ -242,11 +241,13 @@ LogChannel::LogChannel(const char* shortName, const char* fullName, bool enable) void LogChannel::AddListener(LogListener *listener) { std::lock_guard lk(m_listeners_lock); m_listeners.insert(listener); + m_hasListeners = true; } void LogChannel::RemoveListener(LogListener *listener) { std::lock_guard lk(m_listeners_lock); m_listeners.erase(listener); + m_hasListeners = !m_listeners.empty(); } void LogChannel::Trigger(LogTypes::LOG_LEVELS level, const char *msg) { diff --git a/Common/LogManager.h b/Common/LogManager.h index d7ded3de8e..3726552f85 100644 --- a/Common/LogManager.h +++ b/Common/LogManager.h @@ -83,7 +83,7 @@ public: LogTypes::LOG_LEVELS GetLevel() const { return (LogTypes::LOG_LEVELS)level_; } void SetLevel(LogTypes::LOG_LEVELS level) { level_ = level; } - bool HasListeners() const { return !m_listeners.empty(); } + bool HasListeners() const { return m_hasListeners; } // Although not elegant, easy to set with a PopupMultiChoice... int level_; @@ -94,6 +94,7 @@ private: char m_shortName[32]; std::mutex m_listeners_lock; std::set m_listeners; + bool m_hasListeners; }; class ConsoleListener; diff --git a/Core/Debugger/SymbolMap.cpp b/Core/Debugger/SymbolMap.cpp index e3a0b56dae..9e5f07587b 100644 --- a/Core/Debugger/SymbolMap.cpp +++ b/Core/Debugger/SymbolMap.cpp @@ -615,15 +615,21 @@ void SymbolMap::AssignFunctionIndices() { void SymbolMap::UpdateActiveSymbols() { // return; (slow in debug mode) lock_guard guard(lock_); - std::map activeModuleIndexes; - for (auto it = activeModuleEnds.begin(), end = activeModuleEnds.end(); it != end; ++it) { - activeModuleIndexes[it->second.index] = it->second.start; - } activeFunctions.clear(); activeLabels.clear(); activeData.clear(); + // On startup and shutdown, we can skip the rest. Tiny optimization. + if (activeModuleEnds.empty() || (functions.empty() && labels.empty() && data.empty())) { + return; + } + + std::map activeModuleIndexes; + for (auto it = activeModuleEnds.begin(), end = activeModuleEnds.end(); it != end; ++it) { + activeModuleIndexes[it->second.index] = it->second.start; + } + for (auto it = functions.begin(), end = functions.end(); it != end; ++it) { const auto mod = activeModuleIndexes.find(it->second.module); if (it->second.module == 0) { diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 28bc9135c4..7f013d5768 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -337,7 +337,7 @@ skip: for (u32 ahead = fromAddr; ahead < fromAddr + MAX_AHEAD_SCAN; ahead += 4) { MIPSOpcode aheadOp = Memory::Read_Instruction(ahead); - u32 target = GetBranchTargetNoRA(ahead); + u32 target = GetBranchTargetNoRA(ahead, aheadOp); if (target == INVALIDTARGET && ((aheadOp & 0xFC000000) == 0x08000000)) { target = GetJumpTarget(ahead); } @@ -358,7 +358,7 @@ skip: if (closestJumpbackAddr != INVALIDTARGET && furthestJumpbackAddr == INVALIDTARGET) { for (u32 behind = closestJumpbackTarget; behind < fromAddr; behind += 4) { MIPSOpcode behindOp = Memory::Read_Instruction(behind); - u32 target = GetBranchTargetNoRA(behind); + u32 target = GetBranchTargetNoRA(behind, behindOp); if (target == INVALIDTARGET && ((behindOp & 0xFC000000) == 0x08000000)) { target = GetJumpTarget(behind); } @@ -409,7 +409,7 @@ skip: } MIPSOpcode op = Memory::Read_Instruction(addr); - u32 target = GetBranchTargetNoRA(addr); + u32 target = GetBranchTargetNoRA(addr, op); if (target != INVALIDTARGET) { isStraightLeaf = false; if (target > furthestBranch) { diff --git a/Core/MIPS/MIPSCodeUtils.cpp b/Core/MIPS/MIPSCodeUtils.cpp index 727469fccb..7d52278f66 100644 --- a/Core/MIPS/MIPSCodeUtils.cpp +++ b/Core/MIPS/MIPSCodeUtils.cpp @@ -67,6 +67,11 @@ namespace MIPSCodeUtils u32 GetBranchTargetNoRA(u32 addr) { MIPSOpcode op = Memory::Read_Instruction(addr); + return GetBranchTargetNoRA(addr, op); + } + + u32 GetBranchTargetNoRA(u32 addr, MIPSOpcode op) + { if (op != 0) { MIPSInfo info = MIPSGetInfo(op); diff --git a/Core/MIPS/MIPSCodeUtils.h b/Core/MIPS/MIPSCodeUtils.h index 502c42f637..4e2d20d437 100644 --- a/Core/MIPS/MIPSCodeUtils.h +++ b/Core/MIPS/MIPSCodeUtils.h @@ -53,6 +53,7 @@ namespace MIPSCodeUtils u32 GetBranchTarget(u32 addr); // Ignores bltzal/etc. instructions that change RA. u32 GetBranchTargetNoRA(u32 addr); + u32 GetBranchTargetNoRA(u32 addr, MIPSOpcode op); u32 GetJumpTarget(u32 addr); u32 GetSureBranchTarget(u32 addr); bool IsVFPUBranch(MIPSOpcode op); diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 5a29d34903..224baf988b 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -60,11 +60,14 @@ enum MipsEncoding Emu, Rese, NumEncodings, + + Instruc = -1, + Inval = -2, }; struct MIPSInstruction { - int altEncoding; + MipsEncoding altEncoding; const char *name; MIPSComp::MIPSCompileFunc compile; #ifndef FINAL @@ -75,16 +78,16 @@ struct MIPSInstruction MIPSInfo flags; }; -#define INVALID {-2} +#define INVALID {Inval} #define INVALID_X_8 INVALID,INVALID,INVALID,INVALID,INVALID,INVALID,INVALID,INVALID #define N(a) a #ifndef FINAL #define ENCODING(a) {a} -#define INSTR(name, comp, dis, inter, flags) {-1, N(name), comp, dis, inter, MIPSInfo(flags)} +#define INSTR(name, comp, dis, inter, flags) {Instruc, N(name), comp, dis, inter, MIPSInfo(flags)} #else #define ENCODING(a) {a} -#define INSTR(name, comp, dis, inter, flags) {-1, comp, inter, flags} +#define INSTR(name, comp, dis, inter, flags) {Instruc, comp, inter, flags} #endif @@ -816,36 +819,44 @@ const MIPSInstruction tableEMU[4] = { INVALID, }; -const int encodingBits[NumEncodings][2] = -{ - {26, 6}, //IMME - {0, 6}, //Special - {0, 6}, //special2 - {0, 6}, //special3 - {16, 5}, //RegImm - {21, 5}, //Cop0 - {0, 6}, //Cop0CO - {21, 5}, //Cop1 - {16, 5}, //Cop1BC - {0, 6}, //Cop1S - {0, 6}, //Cop1W - {21, 5}, //Cop2 - {16, 2}, //Cop2BC2 - {0, 0}, //Cop2Rese - {23, 3}, //VFPU0 - {23, 3}, //VFPU1 - {23, 3}, //VFPU3 - {21, 5}, //VFPU4Jump - {16, 5}, //VFPU7 - {16, 5}, //VFPU4 - {23, 3}, //VFPU5 - {21, 5}, //VFPU6 - {16, 4}, //VFPUMatrix1 - {16, 5}, //VFPU9 - {6, 5}, //ALLEGREX0 - {24, 2}, //EMUHACK +struct EncodingBitsInfo { + EncodingBitsInfo(u8 shift_, u8 maskBits_) : shift(shift_) { + mask = (1 << maskBits_) - 1; + } + u8 shift; + u32 mask; }; +const EncodingBitsInfo encodingBits[NumEncodings] = +{ + EncodingBitsInfo(26, 6), //IMME + EncodingBitsInfo(0, 6), //Special + EncodingBitsInfo(0, 6), //special2 + EncodingBitsInfo(0, 6), //special3 + EncodingBitsInfo(16, 5), //RegImm + EncodingBitsInfo(21, 5), //Cop0 + EncodingBitsInfo(0, 6), //Cop0CO + EncodingBitsInfo(21, 5), //Cop1 + EncodingBitsInfo(16, 5), //Cop1BC + EncodingBitsInfo(0, 6), //Cop1S + EncodingBitsInfo(0, 6), //Cop1W + EncodingBitsInfo(21, 5), //Cop2 + EncodingBitsInfo(16, 2), //Cop2BC2 + EncodingBitsInfo(0, 0), //Cop2Rese + EncodingBitsInfo(23, 3), //VFPU0 + EncodingBitsInfo(23, 3), //VFPU1 + EncodingBitsInfo(23, 3), //VFPU3 + EncodingBitsInfo(21, 5), //VFPU4Jump + EncodingBitsInfo(16, 5), //VFPU7 + EncodingBitsInfo(16, 5), //VFPU4 + EncodingBitsInfo(23, 3), //VFPU5 + EncodingBitsInfo(21, 5), //VFPU6 + EncodingBitsInfo(16, 4), //VFPUMatrix1 + EncodingBitsInfo(16, 5), //VFPU9 + EncodingBitsInfo(6, 5), //ALLEGREX0 + EncodingBitsInfo(24, 2), //EMUHACK + EncodingBitsInfo(0, 0), //Rese +}; const MIPSInstruction *mipsTables[NumEncodings] = { @@ -874,7 +885,8 @@ const MIPSInstruction *mipsTables[NumEncodings] = tableVFPUMatrixSet1, tableVFPU9, tableALLEGREX0, - tableEMU + tableEMU, + 0, }; @@ -896,23 +908,18 @@ const MIPSInstruction *MIPSGetInstruction(MIPSOpcode op) { MipsEncoding encoding = Imme; const MIPSInstruction *instr = &tableImmediate[op>>26]; - while (instr->altEncoding != -1) + while (instr->altEncoding != Instruc) { - const MIPSInstruction *table = mipsTables[encoding]; - int mask = ((1<> shift) & mask; - instr = &table[subop]; - if (encoding == Rese) - return 0; //invalid instruction - if (!instr) - return 0; - if (instr->altEncoding == -2) + if (instr->altEncoding == Inval) { //ERROR_LOG(CPU, "Invalid instruction %08x in table %i, entry %i", op, (int)encoding, subop); return 0; //invalid instruction } - encoding = (MipsEncoding)instr->altEncoding; + encoding = instr->altEncoding; + + const MIPSInstruction *table = mipsTables[encoding]; + const u32 subop = (op >> encodingBits[encoding].shift) & encodingBits[encoding].mask; + instr = &table[subop]; } //alright, we have a valid MIPS instruction! return instr; diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index 039203b497..298aedc5ce 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -176,9 +176,12 @@ void Clear() memset(m_pVRAM, 0, VRAM_SIZE); } -Opcode Read_Instruction(u32 address, bool resolveReplacements) +static Opcode Read_Instruction(u32 address, bool resolveReplacements, Opcode inst) { - Opcode inst = Opcode(Read_U32(address)); + if (!MIPS_IS_EMUHACK(inst.encoding)) { + return inst; + } + if (MIPS_IS_RUNBLOCK(inst.encoding) && MIPSComp::jit) { JitBlockCache *bc = MIPSComp::jit->GetBlockCache(); int block_num = bc->GetBlockNumberFromEmuHackOp(inst, true); @@ -218,6 +221,18 @@ Opcode Read_Instruction(u32 address, bool resolveReplacements) } } +Opcode Read_Instruction(u32 address, bool resolveReplacements) +{ + Opcode inst = Opcode(Read_U32(address)); + return Read_Instruction(address, resolveReplacements, inst); +} + +Opcode ReadUnchecked_Instruction(u32 address, bool resolveReplacements) +{ + Opcode inst = Opcode(ReadUnchecked_U32(address)); + return Read_Instruction(address, resolveReplacements, inst); +} + Opcode Read_Opcode_JIT(u32 address) { Opcode inst = Opcode(Read_U32(address)); diff --git a/Core/MemMap.h b/Core/MemMap.h index c312ac95f8..81f56df1ee 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -140,6 +140,7 @@ void Write_Opcode_JIT(const u32 _Address, const Opcode _Value); // Should be used by analyzers, disassemblers etc. Does resolve replacements. Opcode Read_Instruction(const u32 _Address, bool resolveReplacements = false); +Opcode ReadUnchecked_Instruction(const u32 _Address, bool resolveReplacements = false); u8 Read_U8(const u32 _Address); u16 Read_U16(const u32 _Address); diff --git a/headless/StubHost.h b/headless/StubHost.h index 47ad6886d1..3247abccf1 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -17,7 +17,8 @@ #pragma once -#include "../Core/Host.h" +#include "Core/Host.h" +#include "Core/Debugger/SymbolMap.h" #define HEADLESSHOST_CLASS HeadlessHost @@ -44,7 +45,7 @@ public: virtual void BootDone() {} virtual bool IsDebuggingEnabled() {return false;} - virtual bool AttemptLoadSymbolMap() {return false;} + virtual bool AttemptLoadSymbolMap() { symbolMap.Clear(); return false; } virtual bool ShouldSkipUI() { return true; }