mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 16:19:28 +01:00
Merge pull request #647 from lioncash/disasm
Common: Introduce the new Gekko disassembler to Common.
This commit is contained in:
commit
6befa34b60
4
Externals/Bochs_disasm/Bochs_disasm.vcxproj
vendored
4
Externals/Bochs_disasm/Bochs_disasm.vcxproj
vendored
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
@ -48,12 +48,10 @@
|
|||||||
<ClInclude Include="config.h" />
|
<ClInclude Include="config.h" />
|
||||||
<ClInclude Include="disasm.h" />
|
<ClInclude Include="disasm.h" />
|
||||||
<ClInclude Include="dis_tables.h" />
|
<ClInclude Include="dis_tables.h" />
|
||||||
<ClInclude Include="PowerPCDisasm.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="dis_decode.cpp" />
|
<ClCompile Include="dis_decode.cpp" />
|
||||||
<ClCompile Include="dis_groups.cpp" />
|
<ClCompile Include="dis_groups.cpp" />
|
||||||
<ClCompile Include="PowerPCDisasm.cpp" />
|
|
||||||
<ClCompile Include="resolve.cpp" />
|
<ClCompile Include="resolve.cpp" />
|
||||||
<ClCompile Include="syntax.cpp" />
|
<ClCompile Include="syntax.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
11
Externals/Bochs_disasm/CMakeLists.txt
vendored
11
Externals/Bochs_disasm/CMakeLists.txt
vendored
@ -1,11 +1,10 @@
|
|||||||
set(SRCS dis_decode.cpp
|
set(SRCS dis_decode.cpp
|
||||||
dis_groups.cpp
|
dis_groups.cpp
|
||||||
resolve.cpp
|
resolve.cpp
|
||||||
syntax.cpp
|
syntax.cpp)
|
||||||
PowerPCDisasm.cpp)
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(SRCS ${SRCS} stdafx.cpp)
|
set(SRCS ${SRCS} stdafx.cpp)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
add_library(bdisasm STATIC ${SRCS})
|
add_library(bdisasm STATIC ${SRCS})
|
||||||
|
2285
Externals/Bochs_disasm/PowerPCDisasm.cpp
vendored
2285
Externals/Bochs_disasm/PowerPCDisasm.cpp
vendored
File diff suppressed because it is too large
Load Diff
29
Externals/Bochs_disasm/PowerPCDisasm.h
vendored
29
Externals/Bochs_disasm/PowerPCDisasm.h
vendored
@ -1,29 +0,0 @@
|
|||||||
/* $VER: ppc_disasm V0.1 (23.05.1998)
|
|
||||||
*
|
|
||||||
* Disassembler module for the PowerPC microprocessor family
|
|
||||||
* Copyright (c) 1998-2000 Frank Wille
|
|
||||||
*
|
|
||||||
* ppc_disasm.c is freeware and may be freely redistributed as long as
|
|
||||||
* no modifications are made and nothing is charged for it.
|
|
||||||
* Non-commercial usage is allowed without any restrictions.
|
|
||||||
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
|
|
||||||
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* v0.1 (23.05.1998) phx
|
|
||||||
* First version, which implements all PowerPC instructions.
|
|
||||||
* v0.0 (09.05.1998) phx
|
|
||||||
* File created.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Yeah, this does not really belong in bochs_disasm, but hey, it's a disasm and it needed a common location...
|
|
||||||
|
|
||||||
#ifndef _POWERPC_DISASM
|
|
||||||
#define _POWERPC_DISASM
|
|
||||||
|
|
||||||
void DisassembleGekko(unsigned int opcode, unsigned int curInstAddr, char* dest, int max_size);
|
|
||||||
const char* GetGPRName(unsigned int index);
|
|
||||||
const char* GetFPRName(unsigned int index);
|
|
||||||
|
|
||||||
#endif
|
|
@ -3,6 +3,7 @@ set(SRCS BreakPoints.cpp
|
|||||||
ColorUtil.cpp
|
ColorUtil.cpp
|
||||||
FileSearch.cpp
|
FileSearch.cpp
|
||||||
FileUtil.cpp
|
FileUtil.cpp
|
||||||
|
GekkoDisassembler.cpp
|
||||||
Hash.cpp
|
Hash.cpp
|
||||||
IniFile.cpp
|
IniFile.cpp
|
||||||
MathUtil.cpp
|
MathUtil.cpp
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
<ClInclude Include="FileUtil.h" />
|
<ClInclude Include="FileUtil.h" />
|
||||||
<ClInclude Include="FixedSizeQueue.h" />
|
<ClInclude Include="FixedSizeQueue.h" />
|
||||||
<ClInclude Include="FPURoundMode.h" />
|
<ClInclude Include="FPURoundMode.h" />
|
||||||
|
<ClInclude Include="GekkoDisassembler.h" />
|
||||||
<ClInclude Include="Hash.h" />
|
<ClInclude Include="Hash.h" />
|
||||||
<ClInclude Include="IniFile.h" />
|
<ClInclude Include="IniFile.h" />
|
||||||
<ClInclude Include="LinearDiskCache.h" />
|
<ClInclude Include="LinearDiskCache.h" />
|
||||||
@ -94,6 +95,7 @@
|
|||||||
<ClCompile Include="ExtendedTrace.cpp" />
|
<ClCompile Include="ExtendedTrace.cpp" />
|
||||||
<ClCompile Include="FileSearch.cpp" />
|
<ClCompile Include="FileSearch.cpp" />
|
||||||
<ClCompile Include="FileUtil.cpp" />
|
<ClCompile Include="FileUtil.cpp" />
|
||||||
|
<ClCompile Include="GekkoDisassembler.cpp" />
|
||||||
<ClCompile Include="Hash.cpp" />
|
<ClCompile Include="Hash.cpp" />
|
||||||
<ClCompile Include="IniFile.cpp" />
|
<ClCompile Include="IniFile.cpp" />
|
||||||
<ClCompile Include="MathUtil.cpp" />
|
<ClCompile Include="MathUtil.cpp" />
|
||||||
@ -140,4 +142,4 @@
|
|||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
@ -70,6 +70,7 @@
|
|||||||
<ClInclude Include="Crypto\bn.h">
|
<ClInclude Include="Crypto\bn.h">
|
||||||
<Filter>Crypto</Filter>
|
<Filter>Crypto</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="GekkoDisassembler.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="BreakPoints.cpp" />
|
<ClCompile Include="BreakPoints.cpp" />
|
||||||
@ -115,6 +116,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="stdafx.cpp" />
|
<ClCompile Include="stdafx.cpp" />
|
||||||
<ClCompile Include="XSaveWorkaround.cpp" />
|
<ClCompile Include="XSaveWorkaround.cpp" />
|
||||||
|
<ClCompile Include="GekkoDisassembler.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="CMakeLists.txt" />
|
<Text Include="CMakeLists.txt" />
|
||||||
|
@ -9,7 +9,7 @@ protected:
|
|||||||
virtual ~DebugInterface() {}
|
virtual ~DebugInterface() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void Disassemble(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
virtual std::string Disassemble(unsigned int /*address*/) { return "NODEBUGGER"; }
|
||||||
virtual void GetRawMemoryString(int /*memory*/, unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
virtual void GetRawMemoryString(int /*memory*/, unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
|
||||||
virtual int GetInstructionSize(int /*instruction*/) {return 1;}
|
virtual int GetInstructionSize(int /*instruction*/) {return 1;}
|
||||||
virtual bool IsAlive() {return true;}
|
virtual bool IsAlive() {return true;}
|
||||||
|
2299
Source/Core/Common/GekkoDisassembler.cpp
Normal file
2299
Source/Core/Common/GekkoDisassembler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
152
Source/Core/Common/GekkoDisassembler.h
Normal file
152
Source/Core/Common/GekkoDisassembler.h
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/* $VER: ppc_disasm.h V1.6 (09.12.2011)
|
||||||
|
*
|
||||||
|
* Disassembler module for the PowerPC microprocessor family
|
||||||
|
* Copyright (c) 1998-2001,2009,2011 Frank Wille
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Modified for use with Dolphin
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
|
class GekkoDisassembler final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::string Disassemble(u32 opcode, u32 current_instruction_address, bool big_endian = true);
|
||||||
|
static const char* GetGPRName(u32 index);
|
||||||
|
static const char* GetFPRName(u32 index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GekkoDisassembler() = delete;
|
||||||
|
|
||||||
|
static void ill(u32 in);
|
||||||
|
static std::string imm(u32 in, int uimm, int type, bool hex);
|
||||||
|
|
||||||
|
static std::string ra_rb(u32 in);
|
||||||
|
static std::string rd_ra_rb(u32 in, int mask);
|
||||||
|
static std::string fd_ra_rb(u32 in, int mask);
|
||||||
|
|
||||||
|
static void trapi(u32 in, unsigned char dmode);
|
||||||
|
static void cmpi(u32 in, int uimm);
|
||||||
|
static void addi(u32 in, const std::string& ext);
|
||||||
|
static size_t branch(u32 in, const char* bname, int aform, int bdisp);
|
||||||
|
static void bc(u32 in);
|
||||||
|
static void bli(u32 in);
|
||||||
|
static void mcrf(u32 in, char c);
|
||||||
|
static void crop(u32 in, const char* n1, const char* n2);
|
||||||
|
static void nooper(u32 in, const char* name, unsigned char dmode);
|
||||||
|
static void rlw(u32 in, const char* name, int i);
|
||||||
|
static void ori(u32 in, const char* name);
|
||||||
|
static void rld(u32 in, const char* name, int i);
|
||||||
|
static void cmp(u32 in);
|
||||||
|
static void trap(u32 in, unsigned char dmode);
|
||||||
|
static void dab(u32 in, const char* name, int mask, int smode, int chkoe, int chkrc, unsigned char dmode);
|
||||||
|
static void rrn(u32 in, const char* name, int smode, int chkoe, int chkrc, unsigned char dmode);
|
||||||
|
static void mtcr(u32 in);
|
||||||
|
static void msr(u32 in, int smode);
|
||||||
|
static void mspr(u32 in, int smode);
|
||||||
|
static void mtb(u32 in);
|
||||||
|
static void sradi(u32 in);
|
||||||
|
static void ldst(u32 in, const char* name, char reg, unsigned char dmode);
|
||||||
|
static void fdabc(u32 in, const char* name, int mask, unsigned char dmode);
|
||||||
|
static void fmr(u32 in);
|
||||||
|
static void fdab(u32 in, const char* name, int mask);
|
||||||
|
static void fcmp(u32 in, char c);
|
||||||
|
static void mtfsb(u32 in, int n);
|
||||||
|
static void ps(u32 inst);
|
||||||
|
static void ps_mem(u32 inst);
|
||||||
|
|
||||||
|
static u32* DoDisassembly(bool big_endian);
|
||||||
|
|
||||||
|
static u32 HelperRotateMask(int r, int mb, int me)
|
||||||
|
{
|
||||||
|
//first make 001111111111111 part
|
||||||
|
unsigned int begin = 0xFFFFFFFF >> mb;
|
||||||
|
//then make 000000000001111 part, which is used to flip the bits of the first one
|
||||||
|
unsigned int end = me < 31 ? (0xFFFFFFFF >> (me + 1)) : 0;
|
||||||
|
//do the bitflip
|
||||||
|
unsigned int mask = begin ^ end;
|
||||||
|
//and invert if backwards
|
||||||
|
if (me < mb)
|
||||||
|
mask = ~mask;
|
||||||
|
//rotate the mask so it can be applied to source reg
|
||||||
|
//return _rotl(mask, 32 - r);
|
||||||
|
return (mask << (32 - r)) | (mask >> r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string ldst_offs(u32 val)
|
||||||
|
{
|
||||||
|
if (val == 0)
|
||||||
|
{
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (val & 0x8000)
|
||||||
|
{
|
||||||
|
return StringFromFormat("-0x%.4X", ((~val) & 0xffff) + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return StringFromFormat("0x%.4X", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SEX12(u32 x)
|
||||||
|
{
|
||||||
|
return x & 0x800 ? (x | 0xFFFFF000) : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InstructionType
|
||||||
|
{
|
||||||
|
PPCINSTR_OTHER = 0, // No additional info for other instr.
|
||||||
|
PPCINSTR_BRANCH = 1, // Branch dest. = PC+displacement
|
||||||
|
PPCINSTR_LDST = 2, // Load/store instruction: displ(sreg)
|
||||||
|
PPCINSTR_IMM = 3, // 16-bit immediate val. in displacement
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Flags
|
||||||
|
{
|
||||||
|
PPCF_ILLEGAL = (1 << 0), // Illegal PowerPC instruction
|
||||||
|
PPCF_UNSIGNED = (1 << 1), // Unsigned immediate instruction
|
||||||
|
PPCF_SUPER = (1 << 2), // Supervisor level instruction
|
||||||
|
PPCF_64 = (1 << 3), // 64-bit only instruction
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32* m_instr; // Pointer to instruction to disassemble
|
||||||
|
static u32* m_iaddr; // Instruction.address., usually the same as instr
|
||||||
|
static std::string m_opcode; // Buffer for opcode, min. 10 chars.
|
||||||
|
static std::string m_operands; // Operand buffer, min. 24 chars.
|
||||||
|
static unsigned char m_type; // Type of instruction, see below
|
||||||
|
static unsigned char m_flags; // Additional flags
|
||||||
|
static unsigned short m_sreg; // Register in load/store instructions
|
||||||
|
static u32 m_displacement; // Branch- or load/store displacement
|
||||||
|
};
|
@ -2,7 +2,9 @@
|
|||||||
// Licensed under GPLv2
|
// Licensed under GPLv2
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "PowerPCDisasm.h"
|
#include <string>
|
||||||
|
|
||||||
|
#include "Common/GekkoDisassembler.h"
|
||||||
|
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
@ -15,31 +17,37 @@
|
|||||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||||
#include "Core/PowerPC/JitCommon/JitBase.h"
|
#include "Core/PowerPC/JitCommon/JitBase.h"
|
||||||
|
|
||||||
void PPCDebugInterface::Disassemble(unsigned int address, char *dest, int max_size)
|
std::string PPCDebugInterface::Disassemble(unsigned int address)
|
||||||
{
|
{
|
||||||
// Memory::ReadUnchecked_U32 seemed to crash on shutdown
|
// Memory::ReadUnchecked_U32 seemed to crash on shutdown
|
||||||
if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN) return;
|
if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN)
|
||||||
|
return "";
|
||||||
|
|
||||||
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||||
{
|
{
|
||||||
if (Memory::IsRAMAddress(address, true, true))
|
if (Memory::IsRAMAddress(address, true, true))
|
||||||
{
|
{
|
||||||
u32 op = Memory::Read_Instruction(address);
|
u32 op = Memory::Read_Instruction(address);
|
||||||
DisassembleGekko(op, address, dest, max_size);
|
std::string disasm = GekkoDisassembler::Disassemble(op, address);
|
||||||
|
|
||||||
UGeckoInstruction inst;
|
UGeckoInstruction inst;
|
||||||
inst.hex = Memory::ReadUnchecked_U32(address);
|
inst.hex = Memory::ReadUnchecked_U32(address);
|
||||||
if (inst.OPCD == 1) {
|
|
||||||
strcat(dest, " (hle)");
|
if (inst.OPCD == 1)
|
||||||
|
{
|
||||||
|
disasm += " (hle)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return disasm;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strcpy(dest, "(No RAM here)");
|
return "(No RAM here)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strcpy(dest, "<unknown>");
|
return "<unknown>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class PPCDebugInterface final : public DebugInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPCDebugInterface(){}
|
PPCDebugInterface(){}
|
||||||
virtual void Disassemble(unsigned int address, char *dest, int max_size) override;
|
virtual std::string Disassemble(unsigned int address) override;
|
||||||
virtual void GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size) override;
|
virtual void GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size) override;
|
||||||
virtual int GetInstructionSize(int /*instruction*/) override {return 4;}
|
virtual int GetInstructionSize(int /*instruction*/) override {return 4;}
|
||||||
virtual bool IsAlive() override;
|
virtual bool IsAlive() override;
|
||||||
|
@ -2,17 +2,18 @@
|
|||||||
// Licensed under GPLv2
|
// Licensed under GPLv2
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "Core/DSP/DSPCore.h"
|
#include "Core/DSP/DSPCore.h"
|
||||||
#include "Core/DSP/DSPDisassembler.h"
|
#include "Core/DSP/DSPDisassembler.h"
|
||||||
#include "Core/DSP/DSPMemoryMap.h"
|
#include "Core/DSP/DSPMemoryMap.h"
|
||||||
#include "Core/HW/DSPLLE/DSPDebugInterface.h"
|
#include "Core/HW/DSPLLE/DSPDebugInterface.h"
|
||||||
#include "Core/HW/DSPLLE/DSPSymbols.h"
|
#include "Core/HW/DSPLLE/DSPSymbols.h"
|
||||||
|
|
||||||
void DSPDebugInterface::Disassemble(unsigned int address, char *dest, int max_size)
|
std::string DSPDebugInterface::Disassemble(unsigned int address)
|
||||||
{
|
{
|
||||||
// we'll treat addresses as line numbers.
|
// we'll treat addresses as line numbers.
|
||||||
strncpy(dest, DSPSymbols::GetLineText(address), max_size);
|
return DSPSymbols::GetLineText(address);
|
||||||
dest[max_size-1] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size)
|
void DSPDebugInterface::GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size)
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
#include "Common/DebugInterface.h"
|
#include "Common/DebugInterface.h"
|
||||||
@ -14,7 +13,7 @@ class DSPDebugInterface final : public DebugInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DSPDebugInterface(){}
|
DSPDebugInterface(){}
|
||||||
virtual void Disassemble(unsigned int address, char *dest, int max_size) override;
|
virtual std::string Disassemble(unsigned int address) override;
|
||||||
virtual void GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size) override;
|
virtual void GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size) override;
|
||||||
virtual int GetInstructionSize(int instruction) override { return 1; }
|
virtual int GetInstructionSize(int instruction) override { return 1; }
|
||||||
virtual bool IsAlive() override;
|
virtual bool IsAlive() override;
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "PowerPCDisasm.h"
|
#include "Common/GekkoDisassembler.h"
|
||||||
|
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
#include "Core/Debugger/Debugger_SymbolMap.h"
|
#include "Core/Debugger/Debugger_SymbolMap.h"
|
||||||
@ -82,10 +81,8 @@ static void Trace(UGeckoInstruction& instCode)
|
|||||||
fregs += StringFromFormat("f%02d: %08" PRIx64 " %08" PRIx64 " ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]);
|
fregs += StringFromFormat("f%02d: %08" PRIx64 " %08" PRIx64 " ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
char ppcInst[256];
|
std::string ppc_inst = GekkoDisassembler::Disassemble(instCode.hex, PC);
|
||||||
DisassembleGekko(instCode.hex, PC, ppcInst, 256);
|
DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRval: %016lx FPSCR: %08x MSR: %08x LR: %08x %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_val[0], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs.c_str(), instCode.hex, ppc_inst.c_str());
|
||||||
|
|
||||||
DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRval: %016lx FPSCR: %08x MSR: %08x LR: %08x %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_val[0], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs.c_str(), instCode.hex, ppcInst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Interpreter::SingleStepInner(void)
|
int Interpreter::SingleStepInner(void)
|
||||||
@ -312,9 +309,8 @@ void Interpreter::unknown_instruction(UGeckoInstruction _inst)
|
|||||||
{
|
{
|
||||||
if (_inst.hex != 0)
|
if (_inst.hex != 0)
|
||||||
{
|
{
|
||||||
char disasm[256];
|
std::string disasm = GekkoDisassembler::Disassemble(Memory::ReadUnchecked_U32(last_pc), last_pc);
|
||||||
DisassembleGekko(Memory::ReadUnchecked_U32(last_pc), last_pc, disasm, 256);
|
NOTICE_LOG(POWERPC, "Last PC = %08x : %s", last_pc, disasm.c_str());
|
||||||
NOTICE_LOG(POWERPC, "Last PC = %08x : %s", last_pc, disasm);
|
|
||||||
Dolphin_Debugger::PrintCallstack();
|
Dolphin_Debugger::PrintCallstack();
|
||||||
_dbg_assert_msg_(POWERPC, 0, "\nIntCPU: Unknown instruction %08x at PC = %08x last_PC = %08x LR = %08x\n", _inst.hex, PC, last_pc, LR);
|
_dbg_assert_msg_(POWERPC, 0, "\nIntCPU: Unknown instruction %08x at PC = %08x last_PC = %08x LR = %08x\n", _inst.hex, PC, last_pc, LR);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "Core/PowerPC/Jit64/JitAsm.h"
|
#include "Core/PowerPC/Jit64/JitAsm.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
#include "PowerPCDisasm.h"
|
#include "Common/GekkoDisassembler.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
@ -613,9 +613,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
|||||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||||
if (gpr.SanityCheck() || fpr.SanityCheck())
|
if (gpr.SanityCheck() || fpr.SanityCheck())
|
||||||
{
|
{
|
||||||
char ppcInst[256];
|
std::string ppc_inst = GekkoDisassembler::Disassemble(ops[i].inst.hex, em_address);
|
||||||
DisassembleGekko(ops[i].inst.hex, em_address, ppcInst, 256);
|
//NOTICE_LOG(DYNA_REC, "Unflushed register: %s", ppc_inst.c_str());
|
||||||
//NOTICE_LOG(DYNA_REC, "Unflushed register: %s", ppcInst);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (js.skipnext) {
|
if (js.skipnext) {
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "disasm.h"
|
#include "disasm.h"
|
||||||
#include "PowerPCDisasm.h"
|
|
||||||
|
|
||||||
|
#include "Common/GekkoDisassembler.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Core/PowerPC/JitCommon/JitBase.h"
|
#include "Core/PowerPC/JitCommon/JitBase.h"
|
||||||
|
|
||||||
@ -29,15 +29,11 @@ u32 Helper_Mask(u8 mb, u8 me)
|
|||||||
|
|
||||||
void LogGeneratedX86(int size, PPCAnalyst::CodeBuffer *code_buffer, const u8 *normalEntry, JitBlock *b)
|
void LogGeneratedX86(int size, PPCAnalyst::CodeBuffer *code_buffer, const u8 *normalEntry, JitBlock *b)
|
||||||
{
|
{
|
||||||
std::string ppcdisasm;
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
char temp[256] = "";
|
|
||||||
const PPCAnalyst::CodeOp &op = code_buffer->codebuffer[i];
|
const PPCAnalyst::CodeOp &op = code_buffer->codebuffer[i];
|
||||||
DisassembleGekko(op.inst.hex, op.address, temp, 256);
|
std::string temp = StringFromFormat("%08x %s", op.address, GekkoDisassembler::Disassemble(op.inst.hex, op.address).c_str());
|
||||||
ppcdisasm += StringFromFormat("%08x %s", op.address, temp);
|
DEBUG_LOG(DYNA_REC, "IR_X86 PPC: %s\n", temp.c_str());
|
||||||
DEBUG_LOG(DYNA_REC, "IR_X86 PPC: %s\n", ppcdisasm.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disassembler x64disasm;
|
disassembler x64disasm;
|
||||||
|
@ -334,9 +334,9 @@ bool PPCSymbolDB::SaveMap(const std::string& filename, bool WithCodes) const
|
|||||||
for (int i = 0; i < space; i += 4)
|
for (int i = 0; i < space; i += 4)
|
||||||
{
|
{
|
||||||
int Address = LastAddress + i;
|
int Address = LastAddress + i;
|
||||||
char disasm[256];
|
|
||||||
debugger->Disassemble(Address, disasm, 256);
|
std::string disasm = debugger->Disassemble(Address);
|
||||||
fprintf(f.GetHandle(),"%08x %i %20s %s\n", Address, 0, TempSym.c_str(), disasm);
|
fprintf(f.GetHandle(),"%08x %i %20s %s\n", Address, 0, TempSym.c_str(), disasm.c_str());
|
||||||
}
|
}
|
||||||
// Write a blank line after each block
|
// Write a blank line after each block
|
||||||
fprintf(f.GetHandle(), "\n");
|
fprintf(f.GetHandle(), "\n");
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Licensed under GPLv2
|
// Licensed under GPLv2
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -189,15 +190,15 @@ void CCodeView::OnMouseUpL(wxMouseEvent& event)
|
|||||||
|
|
||||||
u32 CCodeView::AddrToBranch(u32 addr)
|
u32 CCodeView::AddrToBranch(u32 addr)
|
||||||
{
|
{
|
||||||
char disasm[256];
|
std::string disasm = m_debugger->Disassemble(addr);
|
||||||
m_debugger->Disassemble(addr, disasm, 256);
|
size_t pos = disasm.find("->0x");
|
||||||
const char *mojs = strstr(disasm, "->0x");
|
|
||||||
if (mojs)
|
if (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
u32 dest;
|
std::string hex = disasm.substr(pos + 2);
|
||||||
sscanf(mojs+4,"%08x", &dest);
|
return std::stoul(hex, nullptr, 16);
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,16 +254,14 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
|||||||
|
|
||||||
case IDM_COPYCODE:
|
case IDM_COPYCODE:
|
||||||
{
|
{
|
||||||
char disasm[256];
|
std::string disasm = m_debugger->Disassemble(m_selection);
|
||||||
m_debugger->Disassemble(m_selection, disasm, 256);
|
|
||||||
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm)));
|
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDM_COPYHEX:
|
case IDM_COPYHEX:
|
||||||
{
|
{
|
||||||
char temp[24];
|
std::string temp = StringFromFormat("%08x", m_debugger->ReadInstruction(m_selection));
|
||||||
sprintf(temp, "%08x", m_debugger->ReadInstruction(m_selection));
|
|
||||||
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
|
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -280,9 +279,8 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
|||||||
u32 end = start + symbol->size;
|
u32 end = start + symbol->size;
|
||||||
for (u32 addr = start; addr != end; addr += 4)
|
for (u32 addr = start; addr != end; addr += 4)
|
||||||
{
|
{
|
||||||
char disasm[256];
|
std::string disasm = m_debugger->Disassemble(addr);
|
||||||
m_debugger->Disassemble(addr, disasm, 256);
|
text += StringFromFormat("%08x: ", addr) + disasm + "\r\n";
|
||||||
text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n";
|
|
||||||
}
|
}
|
||||||
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text)));
|
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text)));
|
||||||
}
|
}
|
||||||
@ -478,65 +476,51 @@ void CCodeView::OnPaint(wxPaintEvent& event)
|
|||||||
// If running
|
// If running
|
||||||
if (m_debugger->IsAlive())
|
if (m_debugger->IsAlive())
|
||||||
{
|
{
|
||||||
char dis[256];
|
std::vector<std::string> dis;
|
||||||
m_debugger->Disassemble(address, dis, 256);
|
SplitString(m_debugger->Disassemble(address), '\t', dis);
|
||||||
char* dis2 = strchr(dis, '\t');
|
|
||||||
char desc[256] = "";
|
|
||||||
|
|
||||||
// If we have a code
|
static const size_t VALID_BRANCH_LENGTH = 10;
|
||||||
if (dis2)
|
const std::string& opcode = dis[0];
|
||||||
|
const std::string& operands = dis[1];
|
||||||
|
std::string desc;
|
||||||
|
|
||||||
|
// look for hex strings to decode branches
|
||||||
|
std::string hex_str;
|
||||||
|
size_t pos = operands.find("0x8");
|
||||||
|
if (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
*dis2 = 0;
|
hex_str = operands.substr(pos);
|
||||||
dis2++;
|
|
||||||
// look for hex strings to decode branches
|
|
||||||
const char* mojs = strstr(dis2, "0x8");
|
|
||||||
if (mojs)
|
|
||||||
{
|
|
||||||
for (int k = 0; k < 8; k++)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
for (int j = 0; j < 22; j++)
|
|
||||||
{
|
|
||||||
if (mojs[k + 2] == "0123456789ABCDEFabcdef"[j])
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
mojs = nullptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mojs)
|
|
||||||
{
|
|
||||||
int offs;
|
|
||||||
sscanf(mojs + 2, "%08x", &offs);
|
|
||||||
branches[numBranches].src = rowY1 + m_rowHeight / 2;
|
|
||||||
branches[numBranches].srcAddr = address / m_align;
|
|
||||||
branches[numBranches++].dst = (int)(rowY1 + ((s64)(u32)offs - (s64)(u32)address) * m_rowHeight / m_align + m_rowHeight / 2);
|
|
||||||
sprintf(desc, "-->%s", m_debugger->GetDescription(offs).c_str());
|
|
||||||
dc.SetTextForeground(wxTheColourDatabase->Find("PURPLE")); // the -> arrow illustrations are purple
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dc.SetTextForeground(*wxBLACK);
|
|
||||||
}
|
|
||||||
|
|
||||||
dc.DrawText(StrToWxStr(dis2), 17 + 17*charWidth, rowY1);
|
|
||||||
// ------------
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hex_str.length() == VALID_BRANCH_LENGTH)
|
||||||
|
{
|
||||||
|
u32 offs = std::stoul(hex_str, nullptr, 16);
|
||||||
|
|
||||||
|
branches[numBranches].src = rowY1 + m_rowHeight / 2;
|
||||||
|
branches[numBranches].srcAddr = address / m_align;
|
||||||
|
branches[numBranches++].dst = (int)(rowY1 + ((s64)(u32)offs - (s64)(u32)address) * m_rowHeight / m_align + m_rowHeight / 2);
|
||||||
|
desc = StringFromFormat("-->%s", m_debugger->GetDescription(offs).c_str());
|
||||||
|
dc.SetTextForeground(wxTheColourDatabase->Find("PURPLE")); // the -> arrow illustrations are purple
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dc.SetTextForeground(*wxBLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
dc.DrawText(StrToWxStr(operands), 17 + 17*charWidth, rowY1);
|
||||||
|
// ------------
|
||||||
|
|
||||||
// Show blr as its' own color
|
// Show blr as its' own color
|
||||||
if (strcmp(dis, "blr"))
|
if (opcode == "blr")
|
||||||
dc.SetTextForeground(wxTheColourDatabase->Find("DARK GREEN"));
|
dc.SetTextForeground(wxTheColourDatabase->Find("DARK GREEN"));
|
||||||
else
|
else
|
||||||
dc.SetTextForeground(wxTheColourDatabase->Find("VIOLET"));
|
dc.SetTextForeground(wxTheColourDatabase->Find("VIOLET"));
|
||||||
|
|
||||||
dc.DrawText(StrToWxStr(dis), 17 + (m_plain ? 1*charWidth : 9*charWidth), rowY1);
|
dc.DrawText(StrToWxStr(opcode), 17 + (m_plain ? 1*charWidth : 9*charWidth), rowY1);
|
||||||
|
|
||||||
if (desc[0] == 0)
|
if (desc.empty())
|
||||||
{
|
{
|
||||||
strcpy(desc, m_debugger->GetDescription(address).c_str());
|
desc = m_debugger->GetDescription(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_plain)
|
if (!m_plain)
|
||||||
@ -545,7 +529,7 @@ void CCodeView::OnPaint(wxPaintEvent& event)
|
|||||||
|
|
||||||
//char temp[256];
|
//char temp[256];
|
||||||
//UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE);
|
//UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE);
|
||||||
if (strlen(desc))
|
if (!desc.empty())
|
||||||
{
|
{
|
||||||
dc.DrawText(StrToWxStr(desc), 17 + 35 * charWidth, rowY1);
|
dc.DrawText(StrToWxStr(desc), 17 + 35 * charWidth, rowY1);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <disasm.h> // Bochs
|
#include <disasm.h> // Bochs
|
||||||
#include <PowerPCDisasm.h> // Bochs
|
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/chartype.h>
|
#include <wx/chartype.h>
|
||||||
#include <wx/defs.h>
|
#include <wx/defs.h>
|
||||||
@ -22,6 +21,7 @@
|
|||||||
#include <wx/windowid.h>
|
#include <wx/windowid.h>
|
||||||
|
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
|
#include "Common/GekkoDisassembler.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Core/PowerPC/Gekko.h"
|
#include "Core/PowerPC/Gekko.h"
|
||||||
#include "Core/PowerPC/PPCAnalyst.h"
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
@ -161,9 +161,8 @@ void CJitWindow::Compare(u32 em_address)
|
|||||||
for (u32 i = 0; i < code_block.m_num_instructions; i++)
|
for (u32 i = 0; i < code_block.m_num_instructions; i++)
|
||||||
{
|
{
|
||||||
const PPCAnalyst::CodeOp &op = code_buffer.codebuffer[i];
|
const PPCAnalyst::CodeOp &op = code_buffer.codebuffer[i];
|
||||||
char temp[256];
|
std::string temp = GekkoDisassembler::Disassemble(op.inst.hex, op.address);
|
||||||
DisassembleGekko(op.inst.hex, op.address, temp, 256);
|
sptr += sprintf(sptr, "%08x %s\n", op.address, temp.c_str());
|
||||||
sptr += sprintf(sptr, "%08x %s\n", op.address, temp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add stats to the end of the ppc box since it's generally the shortest.
|
// Add stats to the end of the ppc box since it's generally the shortest.
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <wx/windowid.h>
|
#include <wx/windowid.h>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/GekkoDisassembler.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Core/HW/ProcessorInterface.h"
|
#include "Core/HW/ProcessorInterface.h"
|
||||||
#include "Core/PowerPC/Gekko.h"
|
#include "Core/PowerPC/Gekko.h"
|
||||||
@ -22,9 +23,6 @@ class wxWindow;
|
|||||||
|
|
||||||
// F-zero 80005e60 wtf??
|
// F-zero 80005e60 wtf??
|
||||||
|
|
||||||
extern const char* GetGPRName(unsigned int index);
|
|
||||||
extern const char* GetFPRName(unsigned int index);
|
|
||||||
|
|
||||||
static const char *special_reg_names[] = {
|
static const char *special_reg_names[] = {
|
||||||
"PC", "LR", "CTR", "CR", "FPSCR", "MSR", "SRR0", "SRR1", "Exceptions", "Int Mask", "Int Cause",
|
"PC", "LR", "CTR", "CR", "FPSCR", "MSR", "SRR0", "SRR1", "Exceptions", "Int Mask", "Int Cause",
|
||||||
};
|
};
|
||||||
@ -54,9 +52,9 @@ wxString CRegTable::GetValue(int row, int col)
|
|||||||
{
|
{
|
||||||
switch (col)
|
switch (col)
|
||||||
{
|
{
|
||||||
case 0: return StrToWxStr(GetGPRName(row));
|
case 0: return StrToWxStr(GekkoDisassembler::GetGPRName(row));
|
||||||
case 1: return wxString::Format("%08x", GPR(row));
|
case 1: return wxString::Format("%08x", GPR(row));
|
||||||
case 2: return StrToWxStr(GetFPRName(row));
|
case 2: return StrToWxStr(GekkoDisassembler::GetFPRName(row));
|
||||||
case 3: return wxString::Format("%016llx", riPS0(row));
|
case 3: return wxString::Format("%016llx", riPS0(row));
|
||||||
case 4: return wxString::Format("%016llx", riPS1(row));
|
case 4: return wxString::Format("%016llx", riPS1(row));
|
||||||
default: return wxEmptyString;
|
default: return wxEmptyString;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user