www.pudn.com > potemkin_sourceforPSP.rar > ARMAnalyst.cpp


#include "stdafx.h" 
 
#include "../../Globals.h" 
#include "../MemMap.h" 
#include "ARM.h" 
#include "ARMCompiler.h" 
#include "ARMDis.h" 
#include "ARMTables.h" 
#include "BlockCache.h" 
 
 
//Various ARM code analysis functions 
#define MAX_ANALYZE 10000 
InstructionInfo analyzeBuffer[MAX_ANALYZE]; 
 
 
InstructionInfo &CurrentAnalysis() 
{ 
	return analyzeBuffer[curInstructionsCompiled]; 
} 
 
u32 Analyst_FindEndOfBlock(u32 address, bool thumb) 
{ 
	if (thumb) 
	{ 
		int max = MAX_ANALYZE; 
		while (max--) 
		{ 
			if (THUMBGetInfo(ReadOp16(address)).flags & (END_BASIC_BLOCK|BAD_INSTRUCTION)) 
				return address; 
			address+=2; 
		} 
		LOG(CPU,"error - Analyst found huge block", address); 
	} 
	else 
	{ 
		int max = MAX_ANALYZE; 
		while (max--) 
		{ 
			if (ARMGetInfo(ReadOp32(address)).flags & (END_BASIC_BLOCK|BAD_INSTRUCTION)) 
				return address; 
			address+=4; 
		} 
		LOG(CPU,"error - Analyst found huge block", address); 
	} 
	return -1; 
} 
 
 
//yah it's ugly but hey :) 
int Analyst_GetPotentialDestinations(u32 address, bool thumb, u32 out[2]) 
{ 
	if (thumb) 
	{ 
		u16 op = ReadRealOpTHUMB(address); 
		InstructionInfo info = THUMBGetInfo(op); 
		if (info.flags & BAD_INSTRUCTION) 
			return 0; 
		if ((op&0xF000) == 0xD000)//bcond 
		{ 
			u32 target = address + ((s32)(s8)op)*2+4; 
			out[0] = target; 
			out[1] = address+2; 
			return 2; 
		} 
		else if ((op&0xF800)==0xE000)//b 
		{ 
			u32 target = address + ((s32)SEX11(op))*2+4; 
			out[0] = target; 
			return 1; 
		} 
		else if (((op&0xFF80)==0x4700)||((op&0xFF80)==0x4780)) 
		{ 
			//bx,blx - we know nothing 
			return 0; 
		} 
		else if ((op&0xF800)==0xF000) 
		{ 
			//long branch - we know! 
			bool bx = (op & (1<<11))?true:false; 
			if (bx) 
			{ 
				// we change to arm - we don't analyze inter arm-thumb flag optimizations 
				return 0; 
			} 
			else 
			{ 
				u16 op2 = ReadMem16Unchecked(address+2); 
				u32 offset = SEX11(op)<<12; 
				offset += (op2 & 0x7ff)*2; 
				offset += address+4; 
				if (bx) 
					offset &=~3; 
				out[0] = offset; 
				return 1; 
			} 
		} 
		else 
		{ 
			out[0] = address+2; 
			return 1; 
		} 
	} 
	else 
	{ 
		u32 op = ReadRealOpARM(address); 
		InstructionInfo info = ARMGetInfo(op); 
		if (info.flags & BAD_INSTRUCTION) 
			return 0; 
		if ((op&0x0F000000)==0x0A000000 || (op&0x0F000000)==0x0B000000) 
		{ 
			//B, BL 
			u32 target = address+8+4*SEX24(op&0xFFFFFF); 
			if ((op&0xF0000000) == 0xE0000000) //always? 
			{ 
				out[0] = target; 
				return 1; 
			} 
			else 
			{ 
				out[0] = target; 
				out[1] = address+4; 
				return 2; 
			} 
		} 
		else if (((op&0x0FF000F0)==0x01200030) || ((op&0x0FF000F0)==0x01200010)) 
		{ 
			// we have bx, blx .. we know nothing 
			return 0; 
		} 
		else 
		{ 
			//all other instructions just move to the next :P 
			out[0] = address+4; 
			return 1; 
		} 
	} 
} 
 
// scans forward, and checks if any subsequent code wants flags 
int Analyst_GetWantedFlags(u32 start, int max, bool thumb) 
{ 
	u32 addr = start; 
	int wantedFlags = FL_N|FL_V|FL_Z|FL_C; 
	for (int i=0; istart+8) //makes no sense to spend this time on very small blocks 
		numDests = Analyst_GetPotentialDestinations(end,thumb,dests); 
	else 
		numDests = 0; 
	int size = (end-start)/(thumb?2:4) + 1; 
	if (size>=MAX_ANALYZE-1) 
	{ 
		_dbg_assert_msg_(CPU,0,"Too big block to analyze"); 
	} 
	if (thumb) 
	{ 
		for (int i = 0; i=0; i--) 
	{ 
		int origflags = analyzeBuffer[i].flagsOut; 
		analyzeBuffer[i].flagsOut &= wantedFlags; 
		if (analyzeBuffer[i].cond == COND_AL) 
			wantedFlags &= ~origflags; 
		wantedFlags |= analyzeBuffer[i].flagsIn; 
	} 
} 
 
void Analyst_AnalyzeBlock(u32 address, bool thumb) 
{ 
	u32 end = Analyst_FindEndOfBlock(address, thumb); 
	Analyst_Analyze(address,end,thumb); 
}