void PPCDebugInterface::disasm(unsigned int address, char *dest, int max_size) { // Memory::ReadUnchecked_U32 seemed to crash on shutdown if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN) return; if (Core::GetState() != Core::CORE_UNINITIALIZED) { if (Memory::IsRAMAddress(address, true, true)) { u32 op = Memory::Read_Instruction(address); DisassembleGekko(op, address, dest, max_size); UGeckoInstruction inst; inst.hex = Memory::ReadUnchecked_U32(address); if (inst.OPCD == 1) { strcat(dest, " (hle)"); } } else { strcpy(dest, "(No RAM here)"); } } else { strcpy(dest, "<unknown>"); } }
void Interpreter::unknown_instruction(UGeckoInstruction _inst) { if (_inst.hex != 0) { char disasm[256]; DisassembleGekko(Memory::ReadUnchecked_U32(last_pc), last_pc, disasm, 256); NOTICE_LOG(POWERPC, "Last PC = %08x : %s", last_pc, disasm); 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); } }
void GDisAsmView::OnCPUStepped() { base_addr = ireg.PC - 52; unsigned int curInstAddr = base_addr; int counter = 0; QModelIndex cur_instr_index; model->setRowCount(100); while(true) { u32 opcode = *(u32*)(&Mem_RAM[curInstAddr & RAM_MASK]); char out1[64]; char out2[128]; u32 out3 = 0; memset(out1, 0, sizeof(out1)); memset(out2, 0, sizeof(out2)); // NOTE: out3 (nextInstAddr) seems to be bugged, better don't use it... DisassembleGekko(out1, out2, opcode, curInstAddr, &out3); model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg((uint)curInstAddr, 8, 16, QLatin1Char('0')))); model->setItem(counter, 1, new QStandardItem(QString(out1))); model->setItem(counter, 2, new QStandardItem(QString(out2))); if (ireg.PC == curInstAddr) { model->item(counter, 0)->setBackground(Qt::yellow); model->item(counter, 1)->setBackground(Qt::yellow); model->item(counter, 2)->setBackground(Qt::yellow); cur_instr_index = model->index(counter, 0); } else if (Debugger::IsBreakpoint(curInstAddr)) { model->item(counter, 0)->setBackground(Qt::red); model->item(counter, 1)->setBackground(Qt::red); model->item(counter, 2)->setBackground(Qt::red); } else { model->item(counter, 0)->setBackground(QBrush()); model->item(counter, 1)->setBackground(QBrush()); model->item(counter, 2)->setBackground(QBrush()); } curInstAddr += 4; ++counter; if (counter >= 100) break; } disasm_ui.treeView->resizeColumnToContents(0); disasm_ui.treeView->resizeColumnToContents(1); disasm_ui.treeView->resizeColumnToContents(2); disasm_ui.treeView->scrollTo(cur_instr_index); // QAbstractItemView::PositionAtCenter? }
void Trace( UGeckoInstruction &instCode ) { char reg[25]=""; std::string regs = ""; for (int i=0; i<32; i++) { sprintf(reg, "r%02d: %08x ", i, PowerPC::ppcState.gpr[i]); regs.append(reg); } char freg[25]=""; std::string fregs = ""; for (int i=0; i<32; i++) { sprintf(freg, "f%02d: %08llx %08llx ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); fregs.append(freg); } char ppcInst[256]; DisassembleGekko(instCode.hex, PC, ppcInst, 256); DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs.c_str(), fregs.c_str(), instCode.hex, ppcInst); }
void CJitWindow::Compare(u32 em_address) { u8 *xDis = new u8[1<<18]; memset(xDis, 0, 1<<18); disassembler x64disasm; x64disasm.set_syntax_intel(); int block_num = jit->GetBlockCache()->GetBlockNumberFromStartAddress(em_address); if (block_num < 0) { for (int i = 0; i < 500; i++) { block_num = jit->GetBlockCache()->GetBlockNumberFromStartAddress(em_address - 4 * i); if (block_num >= 0) break; } if (block_num >= 0) { JitBlock *block = jit->GetBlockCache()->GetBlock(block_num); if (!(block->originalAddress <= em_address && block->originalSize + block->originalAddress >= em_address)) block_num = -1; } // Do not merge this "if" with the above - block_num changes inside it. if (block_num < 0) { ppc_box->SetValue(StrToWxStr(StringFromFormat("(non-code address: %08x)", em_address))); x86_box->SetValue(StrToWxStr(StringFromFormat("(no translation)"))); delete[] xDis; return; } } JitBlock *block = jit->GetBlockCache()->GetBlock(block_num); // 800031f0 // == Fill in x86 box const u8 *code = (const u8 *)jit->GetBlockCache()->GetCompiledCodeFromBlock(block_num); u64 disasmPtr = (u64)code; int size = block->codeSize; const u8 *end = code + size; char *sptr = (char*)xDis; int num_x86_instructions = 0; while ((u8*)disasmPtr < end) { #if _M_X86_64 disasmPtr += x64disasm.disasm64(disasmPtr, disasmPtr, (u8*)disasmPtr, sptr); #else disasmPtr += x64disasm.disasm32(disasmPtr, disasmPtr, (u8*)disasmPtr, sptr); #endif sptr += strlen(sptr); *sptr++ = 13; *sptr++ = 10; num_x86_instructions++; } x86_box->SetValue(StrToWxStr((char*)xDis)); // == Fill in ppc box u32 ppc_addr = block->originalAddress; PPCAnalyst::CodeBuffer code_buffer(32000); PPCAnalyst::BlockStats st; PPCAnalyst::BlockRegStats gpa; PPCAnalyst::BlockRegStats fpa; bool broken_block = false; u32 merged_addresses[32]; const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]); int size_of_merged_addresses; if (PPCAnalyst::Flatten(ppc_addr, &size, &st, &gpa, &fpa, broken_block, &code_buffer, size, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses) != 0xffffffff) { sptr = (char*)xDis; for (int i = 0; i < size; i++) { const PPCAnalyst::CodeOp &op = code_buffer.codebuffer[i]; char temp[256]; DisassembleGekko(op.inst.hex, op.address, temp, 256); sptr += sprintf(sptr, "%08x %s\n", op.address, temp); } // Add stats to the end of the ppc box since it's generally the shortest. sptr += sprintf(sptr, "\n"); // Add some generic analysis if (st.isFirstBlockOfFunction) sptr += sprintf(sptr, "(first block of function)\n"); if (st.isLastBlockOfFunction) sptr += sprintf(sptr, "(first block of function)\n"); sptr += sprintf(sptr, "%i estimated cycles\n", st.numCycles); sptr += sprintf(sptr, "Num instr: PPC: %i x86: %i (blowup: %i%%)\n", size, num_x86_instructions, 100 * (num_x86_instructions / size - 1)); sptr += sprintf(sptr, "Num bytes: PPC: %i x86: %i (blowup: %i%%)\n", size * 4, block->codeSize, 100 * (block->codeSize / (4 * size) - 1)); ppc_box->SetValue(StrToWxStr((char*)xDis)); } else { ppc_box->SetValue(StrToWxStr(StringFromFormat( "(non-code address: %08x)", em_address))); x86_box->SetValue("---"); } delete[] xDis; }
GekkoF GekkoCPU::ComparePipeData(u32 LastAddress) { u32 x; u32 RegCmpCRC; u32 MemCRC; u32 RegCRC; u32 CurAddress; static u32 StartedCompare = 0; u32 StartTime; #define CPU_IC 0x00000000 #define CPU_COMPARE_MEM 0 #if(AllowCompareAcrossEXEs) //server, send data u8 RegCompare[sizeof(Gekko_Registers)]; u32 RegOffset; #endif if(PipeIsClient) { for(;PipeHandleData[0] != 0x01 && PipeHandleData[0] != 0xFE;) { SDL_Delay(0); if(PipeHandleData[0] == 0xFF) { HandleSpecialPipeData(); return; } } if(!StartedCompare) { if(ireg.IC < CPU_IC) return; else { //set our flag and wait for the server to be ready StartedCompare = 1; printf("CPU Compare waiting on server for sync\n"); for(;PipeHandleData[0] != 0xFE;) { SDL_Delay(5); } HandleSpecialPipeData(); return; } } RegCmpCRC = *(u32 *)(&PipeHandleData[1]); // memcpy(&TempReg, &ireg, sizeof(ireg)); /* //due to a difference between int and rec, knock off the lower 32bits for(x = 0; x < 32; x++) { TempReg.fpr[x].ps0._u32[0] = 0; TempReg.fpr[x].ps0._u32[1] &= 0xFFFF0000; TempReg.fpr[x].ps1._u32[0] = 0; TempReg.fpr[x].ps1._u32[1] &= 0xFFFF0000; } */ #if(CPU_COMPARE_MEM) RegCRC = GenerateCRC(Mem_RAM, RAM_SIZE); #else RegCRC = GenerateCRC((u8 *)&ireg, sizeof(ireg)); #endif //copy our keys #pragma todo("what is this? commenting out because keys shouldn't be accessed this way") //if(PipeHandleData[5]) // memcpy(emu.keys, (void *)(&PipeHandleData[6]), sizeof(emu.keys)); if(RegCRC == RegCmpCRC) { //return our position to show good PipeHandleData[0] = 0x02; return; } Gekko_Registers CompareRegs; char opcodeStr[32], operandStr[32]; u32 target; u32 opcode; printf("CPU Data Mismatch!\n"); printf("------------------\n\n"); printf("Reg CRC: 0x%08X\tCorrect: 0x%08X\n", RegCRC, RegCmpCRC); // printf("Mem CRC: 0x%08X\tCorrect: 0x%08X\n", MemCRC, MemCmpCRC); //bad, return an invalid pointer PipeHandleData[0] = 0x03; for(;PipeHandleData[0] != 0x01;){SDL_Delay(0);} memcpy(&CompareRegs, &PipeHandleData[1], sizeof(CompareRegs)); //something does not match pause = true; x = 0; CurAddress = LastAddress; while(x != BRANCH_OPCODE) { opcode = Memory_Read32(CurAddress); x = DisassembleGekko(opcodeStr, operandStr, opcode, CurAddress, &target); printf("%08X (%08X): %s\t%s\n", CurAddress, opcode, opcodeStr, operandStr); CurAddress += 4; }; printf("\nPC: 0x%08X\tLast PC: 0x%08X", ireg.PC, iregBackup.PC); if(ireg.PC != CompareRegs.PC) printf("\tCorrect: 0x%08X\n", CompareRegs.PC); else printf("\n"); printf("TBR: 0x%016I64X", ireg.TBR.TBR); if(ireg.TBR.TBR != CompareRegs.TBR.TBR) printf("\tCorrect: 0x%016I64X\n", CompareRegs.TBR.TBR); else printf("\n"); printf("CR: 0x%08X", ireg.CR); if(ireg.CR != CompareRegs.CR) printf("\tCorrect: 0x%08X\n", CompareRegs.CR); else printf("\n"); printf("IC: 0x%08X", ireg.IC); if(ireg.IC != CompareRegs.IC) printf("\tCorrect: 0x%08X\n", CompareRegs.IC); else printf("\n"); printf("MSR: 0x%08X", ireg.MSR); if(ireg.MSR != CompareRegs.MSR) printf("\tCorrect: 0x%08X\n", CompareRegs.MSR); else printf("\n"); printf("FPSCR: 0x%08X", ireg.FPSCR); if(ireg.FPSCR != CompareRegs.FPSCR) printf("\tCorrect: 0x%08X\n", CompareRegs.FPSCR); else printf("\n"); printf("SRR0: 0x%08X\n", SRR0); printf("CTR: 0x%08X\n", CTR); //find out the invalid data for(x=0; x < 32; x++) { printf("GPR %d: Start: 0x%08X\tEnd: 0x%08X", x, iregBackup.gpr[x], ireg.gpr[x]); if(ireg.gpr[x] != CompareRegs.gpr[x]) printf("\tCorrect: 0x%08X\n", CompareRegs.gpr[x]); else printf("\n"); } //find out the invalid data for(x=0; x < 1024; x++) { if(ireg.spr[x] != CompareRegs.spr[x]) printf("SPR %d: Start: 0x%08X\tEnd: 0x%08X\tCorrect: 0x%08X\n", x, iregBackup.spr[x], ireg.spr[x], CompareRegs.spr[x]); } for(x=0; x < 16; x++) { if(ireg.sr[x] != CompareRegs.sr[x]) printf("SR %d: Start: 0x%08X\tEnd: 0x%08X\tCorrect: 0x%08X\n", x, iregBackup.sr[x], ireg.sr[x], CompareRegs.sr[x]); } for(x=0; x < 32; x++) { printf("FPR %d Start: 0x%016I64X-%016I64X\nFPR %d End:0x%016I64X-%016I64X\n", x, iregBackup.fpr[x].ps1._u64, iregBackup.fpr[x].ps0._u64, x, ireg.fpr[x].ps1._u64, ireg.fpr[x].ps0._u64); // if(((ireg.fpr[x].ps0._u32[1] & 0xFFFF0000) != (CompareRegs.fpr[x].ps0._u32[1] & 0xFFFF0000)) || // ((ireg.fpr[x].ps1._u32[1] & 0xFFFF0000) != (CompareRegs.fpr[x].ps1._u32[1] & 0xFFFF0000))) if((ireg.fpr[x].ps0._u32[1] != CompareRegs.fpr[x].ps0._u32[1]) || (ireg.fpr[x].ps1._u32[1] != CompareRegs.fpr[x].ps1._u32[1]) || (ireg.fpr[x].ps0._u32[0] != CompareRegs.fpr[x].ps0._u32[0]) || (ireg.fpr[x].ps1._u32[0] != CompareRegs.fpr[x].ps1._u32[0])) printf("FPR %d Correct: 0x%016I64X-%016I64X\n", x, CompareRegs.fpr[x].ps1._u64, CompareRegs.fpr[x].ps0._u64); printf("\n"); } //tell the cpu do dump it's data DumpInternalData(LastAddress, CurAddress - LastAddress); } else { if(!StartedCompare) { if(ireg.IC < CPU_IC) { //let it pass thru on the client side, client won't skip past due to needing other input PipeHandleData[0] = 0x01; return; } else { StartedCompare = 0x01; //generate the needed crc's for a full compare of memory and cpu RegCRC = GenerateCRC((u8 *)&ireg, sizeof(ireg)); *(u32*)(&PipeHandleData[2]) = RegCRC; MemCRC = GenerateCRC(Mem_RAM, RAM_SIZE); *(u32*)(&PipeHandleData[6]) = MemCRC; PipeHandleData[1] = 'I'; PipeHandleData[0] = 0xFE; printf("CPU Compare waiting on client for sync\n"); for(;PipeHandleData[0] == 0xFE;){SDL_Delay(5);} if(PipeHandleData[0] != 0x02) { printf("Memory or CPU does not match upon instruction count expiration\n"); pause = true; } else printf("Synced at IC %08X\n", CPU_IC); return; } } //if paused then don't allow any of the data to be modified if(pause) return; //generate the register crc //due to a difference between int and rec, knock off the lower 32bits // memcpy(&TempReg, &ireg, sizeof(ireg)); /* for(x = 0; x < 32; x++) { TempReg.fpr[x].ps0._u32[0] = 0; TempReg.fpr[x].ps0._u32[1] &= 0xFFFF0000; TempReg.fpr[x].ps1._u32[0] = 0; TempReg.fpr[x].ps1._u32[1] &= 0xFFFF0000; } */ #if(CPU_COMPARE_MEM) RegCRC = GenerateCRC(Mem_RAM, RAM_SIZE); #else RegCRC = GenerateCRC((u8 *)&ireg, sizeof(ireg)); #endif *(u32*)&PipeHandleData[1] = RegCRC; #pragma todo("what is this? commenting out because keys shouldn't be accessed this way") //copy our keys //if(emu.keychange) //{ // PipeHandleData[5] = 1; // memcpy((void *)(&PipeHandleData[6]), emu.compkeys, sizeof(emu.compkeys)); // memcpy((void *)emu.keys, emu.compkeys, sizeof(emu.keys)); // emu.keychange = FALSE; //} //else //{ PipeHandleData[5] = 0; //} //generate a CRC of the memory // MemCRC = GenerateCRC((u8 *)&Mem_RAM, sizeof(Mem_RAM)); // *(u32*)&PipeHandleData[5] = MemCRC; PipeHandleData[0] = 0x01; StartTime = SDL_GetTicks(); for(;PipeHandleData[0] == 0x01;) { if((SDL_GetTicks() - StartTime) > 5000) { printf("Waiting on client, IC @ 0x%08X\n", ireg.IC); for(;PipeHandleData[0] == 0x01;){SDL_Delay(0);} } } if(PipeHandleData[0] != 0x02) { printf("F****d Up version f****d up\n"); pause = true; memcpy(&PipeHandleData[1], &ireg, sizeof(ireg)); PipeHandleData[0] = 0x01; } } }