-add function to get relevant opcode information for the disassembly

-put it to use to clean up code
This commit is contained in:
Kingcom 2013-07-30 10:14:56 +02:00
parent 0ef12098df
commit 32f1ca91fd
5 changed files with 188 additions and 39 deletions

View file

@ -23,6 +23,7 @@
#include "MIPSAnalyst.h"
#include "MIPSCodeUtils.h"
#include "../Debugger/SymbolMap.h"
#include "../Debugger/DebugInterface.h"
using namespace MIPSCodeUtils;
using namespace std;
@ -530,4 +531,132 @@ namespace MIPSAnalyst
}
return vec;
}
void opInfoSetJump(MipsOpcodeInfo& inf, bool link, u32 target, int reg = -1)
{
inf.isBranch = true;
inf.isLinkedBranch = link;
inf.branchTarget = target;
if (reg != -1)
{
inf.isBranchToRegister = true;
inf.branchRegisterNum = reg;
}
}
inline void opInfoSetBranch(MipsOpcodeInfo& inf, u32 target, bool conditionMet)
{
inf.isBranch = true;
inf.isConditionalBranch = true;
inf.branchConditionMet = conditionMet;
inf.branchTarget = target;
}
inline void opInfoSetDataAccess(MipsOpcodeInfo& inf, int dataSize)
{
inf.isDataAccess = true;
inf.dataSize = dataSize;
s16 imm16 = inf.encodedOpcode & 0xFFFF;
inf.dataAddress = inf.cpu->GetRegValue(0,MIPS_GET_RS(inf.encodedOpcode)) + imm16;
}
MipsOpcodeInfo GetOpcodeInfo(DebugInterface* cpu, u32 address)
{
MipsOpcodeInfo info;
memset(&info,0,sizeof(info));
info.cpu = cpu;
info.opcodeAddress = address;
info.encodedOpcode = Memory::Read_Instruction(address);
u32 op = info.encodedOpcode;
// read everything that could be used
u32 rt = cpu->GetRegValue(0,MIPS_GET_RT(op));
u32 rd = cpu->GetRegValue(0,MIPS_GET_RD(op));
u32 rs = cpu->GetRegValue(0,MIPS_GET_RS(op));
int rsNum = MIPS_GET_RS(op);
int rtNum = MIPS_GET_RT(op);
u32 jumpTarget = GetJumpTarget(address);
u32 branchTarget = GetBranchTarget(address);
switch (MIPS_GET_OP(op))
{
case 0: // special
switch (MIPS_GET_FUNC(op))
{
case 8: // jr
opInfoSetJump(info,false,rs,rsNum);
break;
case 9: // jalr
opInfoSetJump(info,true,rs,rsNum);
break;
}
break;
case 1: // regimm
switch (rtNum)
{
}
break;
case 2: // j
opInfoSetJump(info,false,jumpTarget);
break;
case 3: // jal
opInfoSetJump(info,true,jumpTarget);
break;
case 4: // beq
opInfoSetBranch(info,branchTarget,rt == rs);
if (rtNum == rsNum) // pretend to be unconditional when it de facto is
{
info.isConditionalBranch = false;
}
break;
case 20: // beql
opInfoSetBranch(info,branchTarget,rt == rs);
info.isLikelyBranch = true;
case 5: // bne
opInfoSetBranch(info,branchTarget,rt != rs);
break;
case 21: // bnel
opInfoSetBranch(info,branchTarget,rt != rs);
info.isLikelyBranch = true;
case 6: // blez
opInfoSetBranch(info,branchTarget,((s32)rs) <= 0);
break;
case 22: // blezl
opInfoSetBranch(info,branchTarget,((s32)rs) <= 0);
info.isLikelyBranch = true;
case 7: // bgtz
opInfoSetBranch(info,branchTarget,((s32)rs) > 0);
break;
case 23: // bgtzl
opInfoSetBranch(info,branchTarget,((s32)rs) > 0);
info.isLikelyBranch = true;
break;
case 32: // lb
case 36: // lb
case 40: // sb
opInfoSetDataAccess(info,1);
break;
case 33: // lh
case 37: // lh
case 41: // sh
opInfoSetDataAccess(info,2);
break;
case 34: // lwl
case 35: // lw
case 38: // lwr
case 42: // swl
case 43: // sw
case 46: // swr
opInfoSetDataAccess(info,4);
break;
}
return info;
}
}

View file

@ -19,6 +19,8 @@
#include "../../Globals.h"
class DebugInterface;
namespace MIPSAnalyst
{
void Analyze(u32 address);
@ -63,5 +65,29 @@ namespace MIPSAnalyst
bool IsSyscall(u32 op);
void Shutdown();
typedef struct
{
DebugInterface* cpu;
u32 opcodeAddress;
u32 encodedOpcode;
// branches
u32 branchTarget;
bool isBranch;
bool isLinkedBranch;
bool isLikelyBranch;
bool isConditionalBranch;
bool branchConditionMet;
bool isBranchToRegister;
int branchRegisterNum;
// data access
bool isDataAccess;
int dataSize;
u32 dataAddress;
} MipsOpcodeInfo;
MipsOpcodeInfo GetOpcodeInfo(DebugInterface* cpu, u32 address);
} // namespace MIPSAnalyst

View file

@ -36,6 +36,10 @@
#define MIPS_MAKE_SYSCALL(module, function) GetSyscallOp(module, GetNibByName(module, function))
#define MIPS_MAKE_BREAK() (13) // ! :)
#define MIPS_GET_OP(op) ((op>>26) & 0x3F)
#define MIPS_GET_FUNC(op) (op & 0x3F)
#define MIPS_GET_SA(op) (op>>6 & 0x1F)
#define MIPS_GET_RS(op) ((op>>21) & 0x1F)
#define MIPS_GET_RT(op) ((op>>16) & 0x1F)
#define MIPS_GET_RD(op) ((op>>11) & 0x1F)

View file

@ -8,6 +8,7 @@
#include "Windows/InputBox.h"
#include "Core/MIPS/MIPSAsm.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "Core/Config.h"
#include "Windows/Debugger/CtrlDisAsmView.h"
#include "Windows/Debugger/Debugger_MemoryDlg.h"
@ -343,6 +344,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
for (int i = 0; i < visibleRows+2; i++)
{
unsigned int address=windowStart + i*instructionSize;
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,address);
int rowY1 = rowHeight*i;
int rowY2 = rowHeight*(i+1);
@ -403,6 +405,12 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
const char *dizz = debugger->disasm(address, instructionSize);
parseDisasm(dizz,opcode,arguments);
// display whether the condition of a branch is met
if (info.isConditionalBranch && address == debugger->getPC())
{
strcat(arguments,info.branchConditionMet ? " ; true" : " ; false");
}
int length = (int) strlen(arguments);
if (length != 0) TextOut(hdc,pixelPositions.argumentsStart,rowY1+2,arguments,length);
@ -410,7 +418,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
TextOut(hdc,pixelPositions.opcodeStart,rowY1+2,opcode,(int)strlen(opcode));
SelectObject(hdc,font);
if (branchTarget != -1 && strcmp(opcode,"jal") != 0 && opcode[1] != 0) //unconditional 'b/j' branch
if (info.isConditionalBranch)
{
branches[numBranches].src=rowY1 + rowHeight/2;
branches[numBranches].srcAddr=address/instructionSize;
@ -491,18 +499,12 @@ void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam)
void CtrlDisAsmView::followBranch()
{
char opcode[64],arguments[256];
const char *dizz = debugger->disasm(curAddress, instructionSize);
parseDisasm(dizz,opcode,arguments);
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger,curAddress);
if (branchTarget != -1)
if (info.isBranch)
{
jumpStack.push_back(curAddress);
gotoAddr(branchTarget);
} else if (branchRegister != -1)
{
jumpStack.push_back(curAddress);
gotoAddr(debugger->GetRegValue(0,branchRegister));
gotoAddr(info.branchTarget);
}
}

View file

@ -22,6 +22,7 @@
#include "Core/CPU.h"
#include "Core/HLE/HLE.h"
#include "Core/CoreTiming.h"
#include "Core/MIPS/MIPSAnalyst.h"
#include "base/stringutil.h"
@ -287,42 +288,29 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
CBreakPoints::SetSkipFirst(currentMIPS->pc);
const char* dis = cpu->disasm(cpu->GetPC(),4);
const char* pos = strstr(dis,"->$");
const char* reg = strstr(dis,"->");
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(cpu,cpu->GetPC());
ptr->setDontRedraw(true);
u32 breakpointAddress = cpu->GetPC()+cpu->getInstructionSize(0);
if (memcmp(dis,"jal\t",4) == 0 || memcmp(dis,"jalr\t",5) == 0)
if (info.isBranch)
{
// it's a function call with a delay slot - skip that too
breakpointAddress += cpu->getInstructionSize(0);
} else if (memcmp(dis,"j\t",2) == 0 || memcmp(dis,"b\t",2) == 0)
{
// in case of absolute branches, set the breakpoint at the branch target
sscanf(pos+3,"%08x",&breakpointAddress);
} else if (memcmp(dis,"jr\t",3) == 0)
{
// the same for jumps to registers
int regNum = -1;
for (int i = 0; i < 32; i++)
if (info.isConditionalBranch == false)
{
if (strcasecmp(reg+2,cpu->GetRegName(0,i)) == 0)
if (info.isLinkedBranch) // jal, jalr
{
regNum = i;
break;
// it's a function call with a delay slot - skip that too
breakpointAddress += cpu->getInstructionSize(0);
} else { // j, ...
// in case of absolute branches, set the breakpoint at the branch target
breakpointAddress = info.branchTarget;
}
}
if (regNum == -1) break;
breakpointAddress = cpu->GetRegValue(0,regNum);
} else if (pos != NULL)
{
// get branch target
sscanf(pos+3,"%08x",&breakpointAddress);
CBreakPoints::AddBreakPoint(breakpointAddress,true);
} else { // beq, ...
// set breakpoint at branch target
breakpointAddress = info.branchTarget;
CBreakPoints::AddBreakPoint(breakpointAddress,true);
// also add a breakpoint after the delay slot
breakpointAddress = cpu->GetPC()+2*cpu->getInstructionSize(0);
// and after the delay slot
breakpointAddress = cpu->GetPC()+2*cpu->getInstructionSize(0);
}
}
SetDebugMode(false);