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);
}