Exemplo n.º 1
0
bool IsRegisterUsed(u32 reg, u32 addr)
{
    while (true)
    {
        u32 op = Memory::Read_Instruction(addr);
        u32 info = MIPSGetInfo(op);

        if (
            ((info & IN_RS) ||
             (info & IN_RS_SHIFT) ||
             (info & IN_RS_ADDR))
            &&
            (MIPS_GET_RS(op) == reg)
        )
            return true;
        if ((info & IN_RT) && (MIPS_GET_RT(op) == reg))
            return true;
        if ((info & IS_CONDBRANCH))
            return true; // could also follow both paths
        if ((info & IS_JUMP))
            return true; // could also follow the path
        if ((info & OUT_RT) && (MIPS_GET_RT(op) == reg))
            return false; //the reg got clobbed! yay!
        if ((info & OUT_RD) && (MIPS_GET_RD(op) == reg))
            return false; //the reg got clobbed! yay!
        if ((info & OUT_RA) && (reg == MIPS_REG_RA))
            return false; //the reg got clobbed! yay!
        addr+=4;
    }
    return true;
}
Exemplo n.º 2
0
	bool getDataAccessInfo(MipsOpcodeInfo& info)
	{
		int size = 0;
		
		u32 op = info.encodedOpcode;
		int off = 0;
		switch (MIPS_GET_OP(op))
		{
		case 0x20:		// lb
		case 0x24:		// lbu
		case 0x28:		// sb
			size = 1;
			break;
		case 0x21:		// lh
		case 0x25:		// lhu
		case 0x29:		// sh
			size = 2;
			break;
		case 0x23:		// lw
		case 0x26:		// lwr
		case 0x2B:		// sw
		case 0x2E:		// swr
			size = 4;
			break;
		case 0x22:		// lwl
		case 0x2A:		// swl
			size = 4;
			off = -3;
			break;
		case 0x37:		// ld
		case 0x1B:		// ldr
		case 0x3F:		// sd
		case 0x2D:		// sdr
			size = 8;
			break;
		case 0x1A:		// ldl
		case 0x2C:		// sdl
			size = 8;
			off = -7;
			break;
		}

		if (size == 0)
			return false;

		info.isDataAccess = true;
		info.dataSize = size;

		u32 rs = info.cpu->getRegister(0, (int)MIPS_GET_RS(op));
		s16 imm16 = op & 0xFFFF;
		info.dataAddress = rs + imm16 + off;

		info.hasRelevantAddress = true;
		info.releventAddress = info.dataAddress;
		return true;
	}
Exemplo n.º 3
0
std::vector<int> GetInputRegs(u32 op)
{
    std::vector<int> vec;
    u32 info = MIPSGetInfo(op);
    if ((info & IS_VFPU) == 0)
    {
        if (info & IN_RS) vec.push_back(MIPS_GET_RS(op));
        if (info & IN_RT) vec.push_back(MIPS_GET_RT(op));
    }
    return vec;
}
Exemplo n.º 4
0
bool ReadsFromReg(u32 op, u32 reg)
{
    u32 opinfo = MIPSGetInfo(op);
    if (opinfo & IN_RT)
    {
        if (MIPS_GET_RT(opinfo) == reg)
            return true;
    }
    if (opinfo & (IN_RS | IN_RS_ADDR | IN_RS_SHIFT))
    {
        if (MIPS_GET_RS(opinfo) == reg)
            return true;
    }
    return false; //TODO: there are more cases!
}
Exemplo n.º 5
0
	MipsOpcodeInfo GetOpcodeInfo(DebugInterface* cpu, u32 address) {
		MipsOpcodeInfo info;
		memset(&info, 0, sizeof(info));

		if (cpu->isValidAddress(address) == false) {
			return info;
		}

		info.cpu = cpu;
		info.opcodeAddress = address;
		info.encodedOpcode = cpu->read32(address);
		u32 op = info.encodedOpcode;

		if (getBranchInfo(info) == true)
			return info;

		if (getDataAccessInfo(info) == true)
			return info;

		// gather relevant address for alu operations
		// that's usually the value of the dest register
		switch (MIPS_GET_OP(op)) {
		case 0:		// special
			switch (MIPS_GET_FUNC(op)) {
			case 0x20:	// add
			case 0x21:	// addu
				info.hasRelevantAddress = true;
				info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]+cpu->getRegister(0,MIPS_GET_RT(op))._u32[0];
				break;
			case 0x22:	// sub
			case 0x23:	// subu
				info.hasRelevantAddress = true;
				info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]-cpu->getRegister(0,MIPS_GET_RT(op))._u32[0];
				break;
			}
			break;
		case 0x08:	// addi
		case 0x09:	// adiu
			info.hasRelevantAddress = true;
			info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]+((s16)(op & 0xFFFF));
			break;
		}

		// TODO: rest
/*		// movn, movz
		if (opInfo & IS_CONDMOVE) {
			info.isConditional = true;

			u32 rt = cpu->GetRegValue(0, (int)MIPS_GET_RT(op));
			switch (opInfo & CONDTYPE_MASK) {
			case CONDTYPE_EQ:
				info.conditionMet = (rt == 0);
				break;
			case CONDTYPE_NE:
				info.conditionMet = (rt != 0);
				break;
			}
		}*/

		return info;
	}
Exemplo n.º 6
0
	bool getBranchInfo(MipsOpcodeInfo& info)
	{
		BranchType type = NONE;
		bool link = false;
		bool likely = false;
		bool toRegister = false;
		bool met = false;

		u32 op = info.encodedOpcode;

		u32 opNum = MIPS_GET_OP(op);
		u32 rsNum = MIPS_GET_RS(op);
		u32 rtNum = MIPS_GET_RT(op);
		u32 rs = info.cpu->getRegister(0,rsNum);
		u32 rt = info.cpu->getRegister(0,rtNum);

		switch (MIPS_GET_OP(op))
		{
		case 0x00:		// special
			switch (MIPS_GET_FUNC(op))
			{
			case 0x08:	// jr
				type = JUMP;
				toRegister = true;
				break;
			case 0x09:	// jalr
				type = JUMP;
				toRegister = true;
				link = true;
				break;
			}
			break;
		case 0x01:		// regimm
			switch (MIPS_GET_RT(op))
			{
			case 0x00:		// bltz
			case 0x02:		// bltzl
			case 0x10:		// bltzal
			case 0x12:		// bltzall
				type = BRANCH;
				met = (((s32)rs) < 0);
				likely = (rt & 2) != 0;
				link = rt >= 0x10;
				break;
				
			case 0x01:		// bgez
			case 0x03:		// bgezl
			case 0x11:		// bgezal
			case 0x13:		// bgezall
				type = BRANCH;
				met = (((s32)rs) >= 0);
				likely = (rt & 2) != 0;
				link = rt >= 0x10;
				break;
			}
			break;
		case 0x02:		// j
			type = JUMP;
			break;
		case 0x03:		// jal
			type = JUMP;
			link = true;
			break;
			
		case 0x04:		// beq
		case 0x14:		// beql
			type = BRANCH;
			met = (rt == rs);
			if (MIPS_GET_RT(op) == MIPS_GET_RS(op))	// always true
				info.isConditional = false;
			likely = opNum >= 0x10;
			break;
			
		case 0x05:		// bne
		case 0x15:		// bnel
			type = BRANCH;
			met = (rt != rs);
			if (MIPS_GET_RT(op) == MIPS_GET_RS(op))	// always false
				info.isConditional = false;
			likely = opNum >= 0x10;
			break;
			
		case 0x06:		// blez
		case 0x16:		// blezl
			type = BRANCH;
			met = (((s32)rs) <= 0);
			likely = opNum >= 0x10;
			break;

		case 0x07:		// bgtz
		case 0x17:		// bgtzl
			type = BRANCH;
			met = (((s32)rs) > 0);
			likely = opNum >= 0x10;
			break;
		}

		if (type == NONE)
			return false;

		info.isBranch = true;
		info.isLinkedBranch = link;
		info.isLikelyBranch = true;
		info.isBranchToRegister = toRegister;
		info.isConditional = type == BRANCH;
		info.conditionMet = met;

		switch (type)
		{
		case JUMP:
			if (toRegister)
			{
				info.branchRegisterNum = (int)MIPS_GET_RS(op);
				info.branchTarget = info.cpu->getRegister(0,info.branchRegisterNum)._u32[0];
			} else {
				info.branchTarget =  (info.opcodeAddress & 0xF0000000) | ((op&0x03FFFFFF) << 2);
			}
			break;
		case BRANCH:
			info.branchTarget = info.opcodeAddress + 4 + ((signed short)(op&0xFFFF)<<2);
			break;
		}

		return true;
	}
Exemplo n.º 7
0
	MipsOpcodeInfo GetOpcodeInfo(DebugInterface* cpu, u32 address) {
		MipsOpcodeInfo info;
		memset(&info, 0, sizeof(info));

		if (!cpu->isValidAddress(address))
			return info;

		info.cpu = cpu;
		info.opcodeAddress = address;
		info.encodedOpcode = cpu->read32(address);
		u32 op = info.encodedOpcode;
		const R5900::OPCODE& opcode = R5900::GetInstruction(op);

		// extract all the branch related information
		info.isBranch = (opcode.flags & IS_BRANCH) != 0;
		if (info.isBranch)
		{
			info.isLinkedBranch = (opcode.flags & IS_LINKED) != 0;
			info.isLikelyBranch = (opcode.flags & IS_LIKELY) != 0;

			u64 rs,rt;
			u32 value;
			switch (opcode.flags & BRANCHTYPE_MASK)
			{
			case BRANCHTYPE_JUMP:
				info.isConditional = false;
				info.branchTarget =  (info.opcodeAddress & 0xF0000000) | ((op&0x03FFFFFF) << 2);
				break;
			case BRANCHTYPE_BRANCH:
				info.isConditional = true;
				info.branchTarget = info.opcodeAddress + 4 + ((s16)(op&0xFFFF)<<2);
			
				rs = info.cpu->getRegister(0,MIPS_GET_RS(op))._u64[0];
				rt = info.cpu->getRegister(0,MIPS_GET_RT(op))._u64[0];
				switch (opcode.flags & CONDTYPE_MASK)
				{
				case CONDTYPE_EQ:
					info.conditionMet = (rt == rs);
					if (MIPS_GET_RT(op) == MIPS_GET_RS(op))	// always true
						info.isConditional = false;
					break;
				case CONDTYPE_NE:
					info.conditionMet = (rt != rs);
					if (MIPS_GET_RT(op) == MIPS_GET_RS(op))	// always false
						info.isConditional = false;
					break;
				case CONDTYPE_LEZ:
					info.conditionMet = (((s64)rs) <= 0);
					break;
				case CONDTYPE_GTZ:
					info.conditionMet = (((s64)rs) > 0);
					break;
				case CONDTYPE_LTZ:
					info.conditionMet = (((s64)rs) < 0);
					break;
				case CONDTYPE_GEZ:
					info.conditionMet = (((s64)rs) >= 0);
					break;
				}
				
				break;
			case BRANCHTYPE_REGISTER:
				info.isConditional = false;
				info.isBranchToRegister = true;
				info.branchRegisterNum = (int)MIPS_GET_RS(op);
				info.branchTarget = info.cpu->getRegister(0,info.branchRegisterNum)._u32[0];
				break;
			case BRANCHTYPE_SYSCALL:
				info.isConditional = false;
				info.isSyscall = true;
				info.branchTarget = 0x80000000+0x180;
				break;
			case BRANCHTYPE_ERET:
				info.isConditional = false;
				// probably shouldn't be hard coded like this...
				if (cpuRegs.CP0.n.Status.b.ERL)
				{
					info.branchTarget = cpuRegs.CP0.n.ErrorEPC;
				} else {
					info.branchTarget = cpuRegs.CP0.n.EPC;
				}
				break;
			case BRANCHTYPE_BC1:
				info.isConditional = true;
				value = info.cpu->getRegister(EECAT_FCR,31)._u32[0] & 0x00800000;
				info.branchTarget = info.opcodeAddress + 4 + ((s16)(op&0xFFFF)<<2);

				switch (opcode.flags & CONDTYPE_MASK)
				{
				case CONDTYPE_EQ:
					info.conditionMet = value == 0;
					break;
				case CONDTYPE_NE:
					info.conditionMet = value != 0;
					break;
				}
				break;
			}
		}

		// extract the accessed memory address
		info.isDataAccess = (opcode.flags & IS_MEMORY) != 0;
		if (info.isDataAccess)
		{
			if (opcode.flags & IS_LEFT)
				info.lrType = LOADSTORE_LEFT;
			else if (opcode.flags & IS_RIGHT)
				info.lrType = LOADSTORE_RIGHT;
			
			u32 rs = info.cpu->getRegister(0, (int)MIPS_GET_RS(op));
			s16 imm16 = op & 0xFFFF;
			info.dataAddress = rs + imm16;

			switch (opcode.flags & MEMTYPE_MASK)
			{
			case MEMTYPE_BYTE:
				info.dataSize = 1;
				break;
			case MEMTYPE_HALF:
				info.dataSize = 2;
				break;
			case MEMTYPE_WORD:
				info.dataSize = 4;
				if (info.lrType == LOADSTORE_LEFT)
					info.dataAddress -= 3;
				break;
			case MEMTYPE_DWORD:
				info.dataSize = 8;
				if (info.lrType == LOADSTORE_LEFT)
					info.dataAddress -= 7;
				break;
			case MEMTYPE_QWORD:
				info.dataSize = 16;
				break;
			}
			
			info.hasRelevantAddress = true;
			info.releventAddress = info.dataAddress;
		}

		// gather relevant address for alu operations
		if (opcode.flags & IS_ALU)
		{
			u64 rs,rt;
			rs = info.cpu->getRegister(0,MIPS_GET_RS(op))._u64[0];
			rt = info.cpu->getRegister(0,MIPS_GET_RT(op))._u64[0];

			switch (opcode.flags & ALUTYPE_MASK)
			{
			case ALUTYPE_ADDI:
				info.hasRelevantAddress = true;
				info.releventAddress = rs+((s16)(op & 0xFFFF));
				break;
			case ALUTYPE_ADD:
				info.hasRelevantAddress = true;
				info.releventAddress = rs+rt;
				break;
			case ALUTYPE_SUB:
				info.hasRelevantAddress = true;
				info.releventAddress = rs-rt;
				break;
			case ALUTYPE_CONDMOVE:
				info.isConditional = true;

				switch (opcode.flags & CONDTYPE_MASK)
				{
				case CONDTYPE_EQ:
					info.conditionMet = (rt == 0);
					break;
				case CONDTYPE_NE:
					info.conditionMet = (rt != 0);
					break;
				}
				break;
			}
		}

		return info;
	}
Exemplo n.º 8
0
void DisassemblyFunction::load()
{
	generateBranchLines();

	// gather all branch targets
	std::set<u32> branchTargets;
	for (size_t i = 0; i < lines.size(); i++)
	{
		switch (lines[i].type)
		{
		case LINE_DOWN:
			branchTargets.insert(lines[i].second);
			break;
		case LINE_UP:
			branchTargets.insert(lines[i].first);
			break;
		default:
			break;
		}
	}
	
	DebugInterface* cpu = DisassemblyManager::getCpu();
	u32 funcPos = address;
	u32 funcEnd = address+size;

	u32 nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA);
	u32 opcodeSequenceStart = funcPos;
	while (funcPos < funcEnd)
	{
		if (funcPos == nextData)
		{
			if (opcodeSequenceStart != funcPos)
				addOpcodeSequence(opcodeSequenceStart,funcPos);

			DisassemblyData* data = new DisassemblyData(funcPos,symbolMap.GetDataSize(funcPos),symbolMap.GetDataType(funcPos));
			entries[funcPos] = data;
			lineAddresses.push_back(funcPos);
			funcPos += data->getTotalSize();

			nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA);
			opcodeSequenceStart = funcPos;
			continue;
		}

		// force align
		if (funcPos % 4)
		{
			u32 nextPos = (funcPos+3) & ~3;

			DisassemblyComment* comment = new DisassemblyComment(funcPos,nextPos-funcPos,".align","4");
			entries[funcPos] = comment;
			lineAddresses.push_back(funcPos);
			
			funcPos = nextPos;
			opcodeSequenceStart = funcPos;
			continue;
		}

		MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(cpu,funcPos);
		u32 opAddress = funcPos;
		funcPos += 4;

		// skip branches and their delay slots
		if (opInfo.isBranch)
		{
			funcPos += 4;
			continue;
		}

		// lui
		if (MIPS_GET_OP(opInfo.encodedOpcode) == 0x0F && funcPos < funcEnd && funcPos != nextData)
		{
			MIPSOpcode next = Memory::Read_Instruction(funcPos);
			MIPSInfo nextInfo = MIPSGetInfo(next);

			u32 immediate = ((opInfo.encodedOpcode & 0xFFFF) << 16) + (s16)(next.encoding & 0xFFFF);
			int rt = MIPS_GET_RT(opInfo.encodedOpcode);

			int nextRs = MIPS_GET_RS(next.encoding);
			int nextRt = MIPS_GET_RT(next.encoding);

			// both rs and rt of the second op have to match rt of the first,
			// otherwise there may be hidden consequences if the macro is displayed.
			// also, don't create a macro if something branches into the middle of it
			if (nextRs == rt && nextRt == rt && branchTargets.find(funcPos) == branchTargets.end())
			{
				DisassemblyMacro* macro = NULL;
				switch (MIPS_GET_OP(next.encoding))
				{
				case 0x09:	// addiu
					macro = new DisassemblyMacro(opAddress);
					macro->setMacroLi(immediate,rt);
					funcPos += 4;
					break;
				case 0x20:	// lb
				case 0x21:	// lh
				case 0x23:	// lw
				case 0x24:	// lbu
				case 0x25:	// lhu
				case 0x28:	// sb
				case 0x29:	// sh
				case 0x2B:	// sw
					macro = new DisassemblyMacro(opAddress);
					
					int dataSize;
					switch (nextInfo & MEMTYPE_MASK) {
					case MEMTYPE_BYTE:
						dataSize = 1;
						break;
					case MEMTYPE_HWORD:
						dataSize = 2;
						break;
					case MEMTYPE_WORD:
					case MEMTYPE_FLOAT:
						dataSize = 4;
						break;
					case MEMTYPE_VQUAD:
						dataSize = 16;
						break;
					default:
						return;
					}

					macro->setMacroMemory(MIPSGetName(next),immediate,rt,dataSize);
					funcPos += 4;
					break;
				}

				if (macro != NULL)
				{
					if (opcodeSequenceStart != opAddress)
						addOpcodeSequence(opcodeSequenceStart,opAddress);

					entries[opAddress] = macro;
					for (int i = 0; i < macro->getNumLines(); i++)
					{
						lineAddresses.push_back(macro->getLineAddress(i));
					}

					opcodeSequenceStart = funcPos;
					continue;
				}
			}
		}

		// just a normal opcode
	}

	if (opcodeSequenceStart != funcPos)
		addOpcodeSequence(opcodeSequenceStart,funcPos);
}
Exemplo n.º 9
0
void DisassemblyFunction::load()
{
	generateBranchLines();

	// gather all branch targets
	std::set<u32> branchTargets;
	for (size_t i = 0; i < lines.size(); i++)
	{
		switch (lines[i].type)
		{
		case LINE_DOWN:
			branchTargets.insert(lines[i].second);
			break;
		case LINE_UP:
			branchTargets.insert(lines[i].first);
			break;
		}
	}
	
	u32 funcPos = address;
	u32 funcEnd = address+size;

	u32 nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA);
	u32 opcodeSequenceStart = funcPos;
	while (funcPos < funcEnd)
	{
		if (funcPos == nextData)
		{
			if (opcodeSequenceStart != funcPos)
				addOpcodeSequence(opcodeSequenceStart,funcPos);

			DisassemblyData* data = new DisassemblyData(cpu,funcPos,symbolMap.GetDataSize(funcPos),symbolMap.GetDataType(funcPos));
			entries[funcPos] = data;
			lineAddresses.push_back(funcPos);
			funcPos += data->getTotalSize();

			nextData = symbolMap.GetNextSymbolAddress(funcPos-1,ST_DATA);
			opcodeSequenceStart = funcPos;
			continue;
		}

		// force align
		if (funcPos % 4)
		{
			u32 nextPos = (funcPos+3) & ~3;

			DisassemblyComment* comment = new DisassemblyComment(cpu,funcPos,nextPos-funcPos,".align","4");
			entries[funcPos] = comment;
			lineAddresses.push_back(funcPos);
			
			funcPos = nextPos;
			opcodeSequenceStart = funcPos;
			continue;
		}

		MIPSAnalyst::MipsOpcodeInfo opInfo = MIPSAnalyst::GetOpcodeInfo(cpu,funcPos);
		u32 opAddress = funcPos;
		funcPos += 4;
		
		// skip branches and their delay slots
		if (opInfo.isBranch)
		{
			funcPos += 4;
			continue;
		}
		
		// lui
		if (MIPS_GET_OP(opInfo.encodedOpcode) == 0x0F && funcPos < funcEnd && funcPos != nextData)
		{
			u32 next = cpu->read32(funcPos);

			u32 immediate = ((opInfo.encodedOpcode & 0xFFFF) << 16) + (s16)(next & 0xFFFF);
			u32 immediateOr = ((opInfo.encodedOpcode & 0xFFFF) << 16) | (u16)(next & 0xFFFF);
			int rt = MIPS_GET_RT(opInfo.encodedOpcode);

			int nextRs = MIPS_GET_RS(next);
			int nextRt = MIPS_GET_RT(next);

			// both rs and rt of the second op have to match rt of the first,
			// otherwise there may be hidden consequences if the macro is displayed.
			// also, don't create a macro if something branches into the middle of it
			if (nextRs == rt && nextRt == rt && branchTargets.find(funcPos) == branchTargets.end())
			{
				DisassemblyMacro* macro = NULL;
				switch (MIPS_GET_OP(next))
				{
				case 0x09:	// addiu
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroLi(immediate,rt);
					funcPos += 4;
					break;
				case 0x0D:	// ori
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroLi(immediateOr,rt);
					funcPos += 4;
					break;
				case 0x20:	// lb
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroMemory("lb",immediate,rt,1);
					funcPos += 4;
					break;
				case 0x21:	// lh
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroMemory("lh",immediate,rt,2);
					funcPos += 4;
					break;
				case 0x23:	// lw
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroMemory("lw",immediate,rt,4);
					funcPos += 4;
					break;
				case 0x24:	// lbu
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroMemory("lbu",immediate,rt,1);
					funcPos += 4;
					break;
				case 0x25:	// lhu
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroMemory("lhu",immediate,rt,2);
					funcPos += 4;
					break;
				case 0x28:	// sb
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroMemory("sb",immediate,rt,1);
					funcPos += 4;
					break;
				case 0x29:	// sh
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroMemory("sh",immediate,rt,2);
					funcPos += 4;
				case 0x2B:	// sw
					macro = new DisassemblyMacro(cpu,opAddress);
					macro->setMacroMemory("sw",immediate,rt,4);
					funcPos += 4;
					break;
				}

				if (macro != NULL)
				{
					if (opcodeSequenceStart != opAddress)
						addOpcodeSequence(opcodeSequenceStart,opAddress);

					entries[opAddress] = macro;
					for (int i = 0; i < macro->getNumLines(); i++)
					{
						lineAddresses.push_back(macro->getLineAddress(i));
					}

					opcodeSequenceStart = funcPos;
					continue;
				}
			}
		}

		// just a normal opcode
	}

	if (opcodeSequenceStart != funcPos)
		addOpcodeSequence(opcodeSequenceStart,funcPos);
}
Exemplo n.º 10
0
void Analyze(u32 address)
{
    //set everything to -1 (FF)
    memset(regAnal, 255, sizeof(AnalysisResults)*32);
    for (int i=0; i<32; i++)
    {
        regAnal[i].used=false;
        regAnal[i].readCount=0;
        regAnal[i].writeCount=0;
        regAnal[i].readAsAddrCount=0;
    }

    u32 addr = address;
    bool exitFlag = false;
    while (true)
    {
        u32 op = Memory::Read_Instruction(addr);
        u32 info = MIPSGetInfo(op);

        for (int reg=0; reg < 32; reg++)
        {
            int rs = MIPS_GET_RS(op);
            int rt = MIPS_GET_RT(op);
            int rd = MIPS_GET_RD(op);

            if (
                ((info & IN_RS) && (rs == reg)) ||
                ((info & IN_RS_SHIFT) && (rs == reg)) ||
                ((info & IN_RT) && (rt == reg)))
            {
                if (regAnal[reg].firstRead == -1)
                    regAnal[reg].firstRead = addr;
                regAnal[reg].lastRead = addr;
                regAnal[reg].readCount++;
                regAnal[reg].used=true;
            }
            if (
                ((info & IN_RS_ADDR) && (rs == reg))
            )
            {
                if (regAnal[reg].firstReadAsAddr == -1)
                    regAnal[reg].firstReadAsAddr = addr;
                regAnal[reg].lastReadAsAddr = addr;
                regAnal[reg].readAsAddrCount++;
                regAnal[reg].used=true;
            }
            if (
                ((info & OUT_RT) && (rt == reg)) ||
                ((info & OUT_RD) && (rd == reg)) ||
                ((info & OUT_RA) && (reg == MIPS_REG_RA))
            )
            {
                if (regAnal[reg].firstWrite == -1)
                    regAnal[reg].firstWrite = addr;
                regAnal[reg].lastWrite = addr;
                regAnal[reg].writeCount++;
                regAnal[reg].used=true;
            }
        }

        if (exitFlag) //delay slot done, let's quit!
            break;

        if ((info & IS_JUMP) || (info & IS_CONDBRANCH))
        {
            exitFlag = true; // now do the delay slot
        }

        addr += 4;
    }

    int numUsedRegs=0;
    static int totalUsedRegs=0;
    static int numAnalyzings=0;
    for (int i=0; i<32; i++)
    {
        if (regAnal[i].used)
            numUsedRegs++;
    }
    totalUsedRegs+=numUsedRegs;
    numAnalyzings++;
    DEBUG_LOG(CPU,"[ %08x ] Used regs: %i	 Average: %f",address,numUsedRegs,(float)totalUsedRegs/(float)numAnalyzings);
}