Merge pull request #647 from lioncash/disasm

Common: Introduce the new Gekko disassembler to Common.
This commit is contained in:
Pierre Bourdon 2014-08-03 21:52:08 -07:00
commit 6befa34b60
21 changed files with 2553 additions and 2434 deletions

View File

@ -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>

View File

@ -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})

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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" />

View File

@ -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;}

File diff suppressed because it is too large Load Diff

View 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
};

View File

@ -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>";
} }
} }

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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);
} }

View File

@ -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) {

View File

@ -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;

View File

@ -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");

View File

@ -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);
} }

View File

@ -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.

View File

@ -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;