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>");
	}
}
Example #2
0
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);
	}

}
Example #3
0
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?
}
Example #4
0
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);
}
Example #5
0
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;
}
Example #6
0
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;
		}
	}
}