void CDebugCommandsView::BeginOpEdit(uint32_t address) { CRect listRect; m_CommandList.GetWindowRect(&listRect); ScreenToClient(&listRect); m_bEditing = true; //ShowAddress(address, FALSE); int nItem = (address - m_StartAddress) / 4; CRect itemRect; m_CommandList.GetSubItemRect(nItem, CCommandList::COL_COMMAND, 0, &itemRect); //itemRect.bottom += 0; itemRect.left += listRect.left + 3; itemRect.right += 100; uint32_t opcode; g_MMU->LW_VAddr(address, opcode); char* command = (char*)R4300iOpcodeName(opcode, address); m_OpEdit.ShowWindow(SW_SHOW); m_OpEdit.MoveWindow(&itemRect); m_OpEdit.BringWindowToTop(); m_OpEdit.SetWindowTextA(command); m_OpEdit.SetFocus(); m_OpEdit.SetSelAll(); m_CommandList.RedrawWindow(); m_OpEdit.RedrawWindow(); }
void CCPULog::DumpToFile(const char* path) { FILE* fp = fopen(path, "wb"); if (fp == NULL) { return; } size_t count = GetCount(); for (size_t i = 0; i < count; i++) { CPUState* state = GetEntry(i); char *tokctx; char* szCommand = (char*)R4300iOpcodeName(state->opcode.Hex, state->pc); char* szCmdName = strtok_s((char*)szCommand, "\t", &tokctx); char* szCmdArgs = strtok_s(NULL, "\t", &tokctx); if (szCmdArgs == NULL) { szCmdArgs = ""; } fprintf(fp, "%08X: %08X %s %s\n", state->pc, state->opcode.Hex, szCmdName, szCmdArgs); } fclose(fp); }
void CDebugCommandsView::ShowAddress(uint32_t address, bool top) { if (top == TRUE) { m_StartAddress = address; if (!isStepping()) { // Disable buttons m_ViewPCButton.EnableWindow(FALSE); m_StepButton.EnableWindow(FALSE); m_StepOverButton.EnableWindow(FALSE); m_SkipButton.EnableWindow(FALSE); m_GoButton.EnableWindow(FALSE); m_RegisterTabs.SetColorsEnabled(false); } } else { bool bOutOfView = address < m_StartAddress || address > m_StartAddress + (m_CommandListRows - 1) * 4; if (bOutOfView) { m_StartAddress = address; m_bIgnoreAddrChange = true; m_AddressEdit.SetValue(address, false, true); } if (m_History.size() == 0 || m_History[m_HistoryIndex] != m_StartAddress) { HistoryPushState(); } m_bIgnorePCChange = true; m_PCEdit.SetValue(g_Reg->m_PROGRAM_COUNTER, false, true); // Enable buttons m_ViewPCButton.EnableWindow(TRUE); m_StepButton.EnableWindow(TRUE); m_StepOverButton.EnableWindow(TRUE); m_SkipButton.EnableWindow(TRUE); m_GoButton.EnableWindow(TRUE); m_RegisterTabs.SetColorsEnabled(true); } m_CommandList.SetRedraw(FALSE); m_CommandList.DeleteAllItems(); ClearBranchArrows(); m_bvAnnotatedLines.clear(); CSymbols::EnterCriticalSection(); for (int i = 0; i < m_CommandListRows; i++) { uint32_t opAddr = m_StartAddress + i * 4; m_CommandList.AddItem(i, CCommandList::COL_ARROWS, " "); char addrStr[9]; sprintf(addrStr, "%08X", opAddr); m_CommandList.AddItem(i, CCommandList::COL_ADDRESS, addrStr); COpInfo OpInfo; OPCODE& OpCode = OpInfo.m_OpCode; bool bAddrOkay = false; if (AddressSafe(opAddr)) { bAddrOkay = g_MMU->LW_VAddr(opAddr, OpCode.Hex); } if (!bAddrOkay) { m_CommandList.AddItem(i, CCommandList::COL_COMMAND, "***"); m_bvAnnotatedLines.push_back(false); continue; } char* command = (char*)R4300iOpcodeName(OpCode.Hex, opAddr); char* cmdName = strtok((char*)command, "\t"); char* cmdArgs = strtok(NULL, "\t"); // Show subroutine symbol name for JAL target if (OpCode.op == R4300i_JAL) { uint32_t targetAddr = (0x80000000 | (OpCode.target << 2)); // todo move symbols management to CDebuggerUI const char* targetSymbolName = CSymbols::GetNameByAddress(targetAddr); if (targetSymbolName != NULL) { cmdArgs = (char*)targetSymbolName; } } // Detect reads and writes to mapped registers, cart header data, etc const char* annotation = NULL; bool bLoadStoreAnnotation = false; if (OpInfo.IsLoadStoreCommand()) { for (int offset = -4; offset > -24; offset -= 4) { if (!AddressSafe(opAddr + offset)) { break; } OPCODE OpCodeTest; bAddrOkay = g_MMU->LW_VAddr(opAddr + offset, OpCodeTest.Hex); if (!bAddrOkay) { break; } if (OpCodeTest.op != R4300i_LUI) { continue; } if (OpCodeTest.rt != OpCode.rs) { continue; } uint32_t memAddr = (OpCodeTest.immediate << 16) + (short)OpCode.offset; annotation = CSymbols::GetNameByAddress(memAddr); if (annotation == NULL) { annotation = GetDataAddressNotes(memAddr); } break; } } if (annotation == NULL) { annotation = GetCodeAddressNotes(opAddr); } else { bLoadStoreAnnotation = true; } m_CommandList.AddItem(i, CCommandList::COL_COMMAND, cmdName); m_CommandList.AddItem(i, CCommandList::COL_PARAMETERS, cmdArgs); // Show routine symbol name for this address const char* routineSymbolName = CSymbols::GetNameByAddress(opAddr); if (routineSymbolName != NULL) { m_CommandList.AddItem(i, CCommandList::COL_SYMBOL, routineSymbolName); m_bvAnnotatedLines.push_back(false); } else if (annotation != NULL) { const char* annotationFormat = bLoadStoreAnnotation ? "// (%s)" : "// %s"; m_CommandList.AddItem(i, CCommandList::COL_SYMBOL, stdstr_f(annotationFormat, annotation).c_str()); m_bvAnnotatedLines.push_back(true); } else { m_bvAnnotatedLines.push_back(false); } // Add arrow for branch instruction if (OpInfo.IsBranch()) { int startPos = i; int endPos = startPos + (int16_t)OpCode.offset + 1; AddBranchArrow(startPos, endPos); } // Branch arrow for close J if (OpCode.op == R4300i_J) { uint32_t target = (OpCode.target << 2); int dist = target - (opAddr & 0x3FFFFFF); if (abs(dist) < 0x10000) { int startPos = i; int endPos = startPos + (dist / 4); AddBranchArrow(startPos, endPos); } } } CSymbols::LeaveCriticalSection(); if (!top) // update registers when called via breakpoint/stepping { m_RegisterTabs.RefreshEdits(); } RefreshBreakpointList(); m_CommandList.SetRedraw(TRUE); }
bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & ContinuePC, bool & LikelyBranch, bool & IncludeDelaySlot, bool & EndBlock, bool & PermLoop) { TargetPC = (uint32_t)-1; ContinuePC = (uint32_t)-1; LikelyBranch = false; IncludeDelaySlot = false; EndBlock = false; PermLoop = false; OPCODE Command; if (!g_MMU->LW_VAddr(PC, Command.Hex)) { g_Notify->BreakPoint(__FILE__, __LINE__); return false; } #ifdef _DEBUG const char * Name = R4300iOpcodeName(Command.Hex, PC); CPU_Message(" 0x%08X %s", PC, Name); #endif switch (Command.op) { case R4300i_SPECIAL: switch (Command.funct) { case R4300i_SPECIAL_SLL: case R4300i_SPECIAL_SRL: case R4300i_SPECIAL_SRA: case R4300i_SPECIAL_SLLV: case R4300i_SPECIAL_SRLV: case R4300i_SPECIAL_SRAV: case R4300i_SPECIAL_MFHI: case R4300i_SPECIAL_MTHI: case R4300i_SPECIAL_MFLO: case R4300i_SPECIAL_MTLO: case R4300i_SPECIAL_DSLLV: case R4300i_SPECIAL_DSRLV: case R4300i_SPECIAL_DSRAV: case R4300i_SPECIAL_ADD: case R4300i_SPECIAL_ADDU: case R4300i_SPECIAL_SUB: case R4300i_SPECIAL_SUBU: case R4300i_SPECIAL_AND: case R4300i_SPECIAL_OR: case R4300i_SPECIAL_XOR: case R4300i_SPECIAL_NOR: case R4300i_SPECIAL_SLT: case R4300i_SPECIAL_SLTU: case R4300i_SPECIAL_DADD: case R4300i_SPECIAL_DADDU: case R4300i_SPECIAL_DSUB: case R4300i_SPECIAL_DSUBU: case R4300i_SPECIAL_DSLL: case R4300i_SPECIAL_DSRL: case R4300i_SPECIAL_DSRA: case R4300i_SPECIAL_DSLL32: case R4300i_SPECIAL_DSRL32: case R4300i_SPECIAL_DSRA32: case R4300i_SPECIAL_MULT: case R4300i_SPECIAL_MULTU: case R4300i_SPECIAL_DIV: case R4300i_SPECIAL_DIVU: case R4300i_SPECIAL_DMULT: case R4300i_SPECIAL_DMULTU: case R4300i_SPECIAL_DDIV: case R4300i_SPECIAL_DDIVU: break; case R4300i_SPECIAL_JALR: case R4300i_SPECIAL_JR: EndBlock = true; IncludeDelaySlot = true; break; case R4300i_SPECIAL_SYSCALL: case R4300i_SPECIAL_BREAK: EndBlock = true; break; default: g_Notify->BreakPoint(__FILE__, __LINE__); return false; } break; case R4300i_REGIMM: switch (Command.rt) { case R4300i_REGIMM_BLTZ: case R4300i_REGIMM_BLTZAL: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; if (TargetPC == PC + 8) { TargetPC = (uint32_t)-1; } else { if (TargetPC == PC && !DelaySlotEffectsCompare(PC, Command.rs, 0)) { PermLoop = true; } ContinuePC = PC + 8; IncludeDelaySlot = true; } break; case R4300i_REGIMM_BGEZ: case R4300i_REGIMM_BGEZAL: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; if (TargetPC == PC + 8) { TargetPC = (uint32_t)-1; } else { if (TargetPC == PC) { if (Command.rs == 0) { TargetPC = (uint32_t)-1; EndBlock = true; } else { if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) { PermLoop = true; } } } if (Command.rs != 0) { ContinuePC = PC + 8; } IncludeDelaySlot = true; } break; case R4300i_REGIMM_BLTZL: case R4300i_REGIMM_BGEZL: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; if (TargetPC == PC) { if (!DelaySlotEffectsCompare(PC, Command.rs, 0)) { PermLoop = true; } } ContinuePC = PC + 8; LikelyBranch = true; IncludeDelaySlot = true; break; default: if (Command.Hex == 0x0407000D) { EndBlock = true; break; } g_Notify->BreakPoint(__FILE__, __LINE__); return false; } break; case R4300i_J: TargetPC = (PC & 0xF0000000) + (Command.target << 2); if (TargetPC == PC) { PermLoop = true; } IncludeDelaySlot = true; break; case R4300i_JAL: EndBlock = true; IncludeDelaySlot = true; break; case R4300i_BEQ: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; if (TargetPC == PC + 8) { TargetPC = (uint32_t)-1; } else { if (Command.rs != 0 || Command.rt != 0) { ContinuePC = PC + 8; } if (TargetPC == PC && !DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) { PermLoop = true; } IncludeDelaySlot = true; } break; case R4300i_BNE: case R4300i_BLEZ: case R4300i_BGTZ: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; if (TargetPC == PC + 8) { TargetPC = (uint32_t)-1; } else { if (TargetPC == PC) { if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) { PermLoop = true; } } ContinuePC = PC + 8; IncludeDelaySlot = true; } break; case R4300i_CP0: switch (Command.rs) { case R4300i_COP0_MT: case R4300i_COP0_MF: break; default: if ((Command.rs & 0x10) != 0) { switch (Command.funct) { case R4300i_COP0_CO_TLBR: case R4300i_COP0_CO_TLBWI: case R4300i_COP0_CO_TLBWR: case R4300i_COP0_CO_TLBP: break; case R4300i_COP0_CO_ERET: EndBlock = true; break; default: g_Notify->BreakPoint(__FILE__, __LINE__); return false; } } else { g_Notify->BreakPoint(__FILE__, __LINE__); return false; } break; } break; case R4300i_CP1: switch (Command.fmt) { case R4300i_COP1_MF: case R4300i_COP1_DMF: case R4300i_COP1_CF: case R4300i_COP1_MT: case R4300i_COP1_DMT: case R4300i_COP1_CT: case R4300i_COP1_S: case R4300i_COP1_D: case R4300i_COP1_W: case R4300i_COP1_L: break; case R4300i_COP1_BC: switch (Command.ft) { case R4300i_COP1_BC_BCF: case R4300i_COP1_BC_BCT: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; if (TargetPC == PC + 8) { TargetPC = (uint32_t)-1; } else { if (TargetPC == PC) { g_Notify->BreakPoint(__FILE__, __LINE__); } ContinuePC = PC + 8; IncludeDelaySlot = true; } break; case R4300i_COP1_BC_BCFL: case R4300i_COP1_BC_BCTL: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; if (TargetPC == PC) { g_Notify->BreakPoint(__FILE__, __LINE__); } ContinuePC = PC + 8; LikelyBranch = true; IncludeDelaySlot = true; break; default: g_Notify->BreakPoint(__FILE__, __LINE__); } break; default: g_Notify->BreakPoint(__FILE__, __LINE__); return false; } break; case R4300i_ANDI: case R4300i_ORI: case R4300i_XORI: case R4300i_LUI: case R4300i_ADDI: case R4300i_ADDIU: case R4300i_SLTI: case R4300i_SLTIU: case R4300i_DADDI: case R4300i_DADDIU: case R4300i_LDL: case R4300i_LDR: case R4300i_LB: case R4300i_LH: case R4300i_LWL: case R4300i_LW: case R4300i_LBU: case R4300i_LHU: case R4300i_LWR: case R4300i_LWU: case R4300i_SB: case R4300i_SH: case R4300i_SWL: case R4300i_SW: case R4300i_SDL: case R4300i_SDR: case R4300i_SWR: case R4300i_CACHE: case R4300i_LL: case R4300i_LWC1: case R4300i_LDC1: case R4300i_LD: case R4300i_SC: case R4300i_SWC1: case R4300i_SDC1: case R4300i_SD: break; case R4300i_BEQL: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; if (TargetPC == PC) { if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) { PermLoop = true; } } if (Command.rs != 0 || Command.rt != 0) { ContinuePC = PC + 8; } IncludeDelaySlot = true; LikelyBranch = true; break; case R4300i_BNEL: case R4300i_BLEZL: case R4300i_BGTZL: TargetPC = PC + ((int16_t)Command.offset << 2) + 4; ContinuePC = PC + 8; if (TargetPC == PC) { if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt)) { PermLoop = true; } } LikelyBranch = true; IncludeDelaySlot = true; break; default: if (Command.Hex == 0x7C1C97C0 || Command.Hex == 0xF1F3F5F7) { EndBlock = true; break; } g_Notify->BreakPoint(__FILE__, __LINE__); return false; } return true; }