Esempio n. 1
0
bool CCodeBlock::Compile()
{
    CPU_Message("====== Code Block ======");
    CPU_Message("Native entry point: %X", CompiledLocation());
    CPU_Message("Start of Block: %X", VAddrEnter());
    CPU_Message("No of Sections: %d", NoOfSections());
    CPU_Message("====== recompiled code ======");

    m_RecompilerOps->EnterCodeBlock();
    if (g_System->bLinkBlocks())
    {
        while (m_EnterSection->GenerateNativeCode(NextTest()));
    }
    else
    {
        if (!m_EnterSection->GenerateNativeCode(NextTest()))
        {
            return false;
        }
    }
    m_RecompilerOps->CompileExitCode();

    uint32_t PAddr;
    g_TransVaddr->TranslateVaddr(VAddrFirst(), PAddr);
    MD5(g_MMU->Rdram() + PAddr, (VAddrLast() - VAddrFirst()) + 4).get_digest(m_Hash);

#if defined(ANDROID) && (defined(__arm__) || defined(_M_ARM))
    __clear_cache_android((uint8_t *)((uint32_t)m_CompiledLocation & ~1), (uint8_t *)(*g_RecompPos));
#endif
    return true;
}
Esempio n. 2
0
void CCodeBlock::CompileExitCode()
{
    for (EXIT_LIST::iterator ExitIter = m_ExitInfo.begin(); ExitIter != m_ExitInfo.end(); ExitIter++)
    {
        CPU_Message("");
        CPU_Message("      $Exit_%d",ExitIter->ID);
        SetJump32(ExitIter->JumpLoc,(uint32_t *)m_RecompPos);
        m_NextInstruction = ExitIter->NextInstruction;
        m_EnterSection->CompileExit((uint32_t)-1, ExitIter->TargetPC,ExitIter->ExitRegSet,ExitIter->reason,true,NULL);
    }
}
Esempio n. 3
0
void MmxUnpackHighWord(int Dest, int Source) {
	BYTE x86Command = 0;

	CPU_Message("      punpckhwd %s, %s", mmx_Name(Dest), mmx_Name(Source));

	switch (Dest) {
	case x86_MM0: x86Command = 0 << 3; break;
	case x86_MM1: x86Command = 1 << 3; break;
	case x86_MM2: x86Command = 2 << 3; break;
	case x86_MM3: x86Command = 3 << 3; break;
	case x86_MM4: x86Command = 4 << 3; break;
	case x86_MM5: x86Command = 5 << 3; break;
	case x86_MM6: x86Command = 6 << 3; break;
	case x86_MM7: x86Command = 7 << 3; break;
	}
	switch (Source) {
	case x86_MM0: x86Command |= 0; break;
	case x86_MM1: x86Command |= 1; break;
	case x86_MM2: x86Command |= 2; break;
	case x86_MM3: x86Command |= 3; break;
	case x86_MM4: x86Command |= 4; break;
	case x86_MM5: x86Command |= 5; break;
	case x86_MM6: x86Command |= 6; break;
	case x86_MM7: x86Command |= 7; break;
	}
	PUTDST16(RecompPos,0x690f);
	PUTDST8(RecompPos, 0xC0 | x86Command);
}
Esempio n. 4
0
void MmxCompareGreaterWordRegToReg(int Dest, int Source) {
	BYTE x86Command = 0;

	CPU_Message("      pcmpgtw %s, %s", mmx_Name(Dest), mmx_Name(Source));

	switch (Dest) {
	case x86_MM0: x86Command = 0 << 3; break;
	case x86_MM1: x86Command = 1 << 3; break;
	case x86_MM2: x86Command = 2 << 3; break;
	case x86_MM3: x86Command = 3 << 3; break;
	case x86_MM4: x86Command = 4 << 3; break;
	case x86_MM5: x86Command = 5 << 3; break;
	case x86_MM6: x86Command = 6 << 3; break;
	case x86_MM7: x86Command = 7 << 3; break;
	}
	switch (Source) {
	case x86_MM0: x86Command |= 0; break;
	case x86_MM1: x86Command |= 1; break;
	case x86_MM2: x86Command |= 2; break;
	case x86_MM3: x86Command |= 3; break;
	case x86_MM4: x86Command |= 4; break;
	case x86_MM5: x86Command |= 5; break;
	case x86_MM6: x86Command |= 6; break;
	case x86_MM7: x86Command |= 7; break;
	}
	PUTDST16(RecompPos,0x650f);
	PUTDST8(RecompPos, 0xC0 | x86Command);
}
Esempio n. 5
0
void SseXorRegToReg(int Dest, int Source) {
	BYTE x86Command = 0;

	CPU_Message("      xorps %s, %s", sse_Name(Dest), sse_Name(Source));

	switch (Dest) {
	case x86_XMM0: x86Command = 0x00; break;
	case x86_XMM1: x86Command = 0x08; break;
	case x86_XMM2: x86Command = 0x10; break;
	case x86_XMM3: x86Command = 0x18; break;
	case x86_XMM4: x86Command = 0x20; break;
	case x86_XMM5: x86Command = 0x28; break;
	case x86_XMM6: x86Command = 0x30; break;
	case x86_XMM7: x86Command = 0x38; break;
	}
	switch (Source) {
	case x86_XMM0: x86Command += 0x00; break;
	case x86_XMM1: x86Command += 0x01; break;
	case x86_XMM2: x86Command += 0x02; break;
	case x86_XMM3: x86Command += 0x03; break;
	case x86_XMM4: x86Command += 0x04; break;
	case x86_XMM5: x86Command += 0x05; break;
	case x86_XMM6: x86Command += 0x06; break;
	case x86_XMM7: x86Command += 0x07; break;
	}
	PUTDST16(RecompPos,0x570f);
	PUTDST8(RecompPos, 0xC0 | x86Command);
}
Esempio n. 6
0
void SseShuffleReg(int Dest, int Source, BYTE Immed) {
	BYTE x86Command = 0;

	CPU_Message("      shufps %s, %s, %02X", sse_Name(Dest), sse_Name(Source), Immed);

	switch (Dest) {
	case x86_XMM0: x86Command = 0x00; break;
	case x86_XMM1: x86Command = 0x08; break;
	case x86_XMM2: x86Command = 0x10; break;
	case x86_XMM3: x86Command = 0x18; break;
	case x86_XMM4: x86Command = 0x20; break;
	case x86_XMM5: x86Command = 0x28; break;
	case x86_XMM6: x86Command = 0x30; break;
	case x86_XMM7: x86Command = 0x38; break;
	}
	switch (Source) {
	case x86_XMM0: x86Command += 0x00; break;
	case x86_XMM1: x86Command += 0x01; break;
	case x86_XMM2: x86Command += 0x02; break;
	case x86_XMM3: x86Command += 0x03; break;
	case x86_XMM4: x86Command += 0x04; break;
	case x86_XMM5: x86Command += 0x05; break;
	case x86_XMM6: x86Command += 0x06; break;
	case x86_XMM7: x86Command += 0x07; break;
	}
	PUTDST16(RecompPos,0xC60f);
	PUTDST8(RecompPos, 0xC0 | x86Command);
	PUTDST8(RecompPos, Immed);
}
Esempio n. 7
0
void SseMoveAlignedN64MemToReg(int sseReg, int AddrReg) {
	BYTE x86Command = 0;

	CPU_Message("      movaps %s, xmmword ptr [Dmem+%s]",sse_Name(sseReg), x86_Name(AddrReg));

	switch (sseReg) {
	case x86_XMM0: x86Command = 0x80; break;
	case x86_XMM1: x86Command = 0x88; break;
	case x86_XMM2: x86Command = 0x90; break;
	case x86_XMM3: x86Command = 0x98; break;
	case x86_XMM4: x86Command = 0xA0; break;
	case x86_XMM5: x86Command = 0xA8; break;
	case x86_XMM6: x86Command = 0xB0; break;
	case x86_XMM7: x86Command = 0xB8; break;
	}	
	switch (AddrReg) {
	case x86_EAX: x86Command += 0x00; break;
	case x86_EBX: x86Command += 0x03; break;
	case x86_ECX: x86Command += 0x01; break;
	case x86_EDX: x86Command += 0x02; break;
	case x86_ESI: x86Command += 0x06; break;
	case x86_EDI: x86Command += 0x07; break;
	case x86_ESP: x86Command += 0x04; break;
	case x86_EBP: x86Command += 0x05; break;
	}

	PUTDST16(RecompPos,0x280f);
	PUTDST8(RecompPos, x86Command);
	PUTDSTPTR(RecompPos, RSPInfo.DMEM);
}
Esempio n. 8
0
bool CCodeBlock::Compile()
{
    CPU_Message("====== Code Block ======");
    CPU_Message("x86 code at: %X",CompiledLocation());
    CPU_Message("Start of Block: %X",VAddrEnter() );
    CPU_Message("No of Sections: %d",NoOfSections() );
    CPU_Message("====== recompiled code ======");

    EnterCodeBlock();

    if (g_SyncSystem)
    {
        //if ((uint32_t)BlockInfo.CompiledLocation == 0x60A7B73B)
        //{
        //	X86BreakPoint(__FILEW__,__LINE__);
        //}
        //MoveConstToVariable((uint32_t)BlockInfo.CompiledLocation,&CurrentBlock,"CurrentBlock");
    }

    if (g_System->bLinkBlocks())
    {
        while (m_EnterSection->GenerateX86Code(NextTest()));
    }
    else
    {
        if (!m_EnterSection->GenerateX86Code(NextTest()))
        {
            return false;
        }
    }
    CompileExitCode();

    uint32_t PAddr;
    g_TransVaddr->TranslateVaddr(VAddrFirst(),PAddr);
    MD5(g_MMU->Rdram() + PAddr,(VAddrLast() - VAddrFirst()) + 4).get_digest(m_Hash);

    return true;
}
Esempio n. 9
0
void MmxPmulhwRegToVariable(int Dest, void * Variable, char * VariableName) {
	BYTE x86Command = 0;

	CPU_Message("      pmulhw %s, [%s]", mmx_Name(Dest), VariableName);

	switch (Dest) {
	case x86_MM0: x86Command = 0x05; break;
	case x86_MM1: x86Command = 0x0D; break;
	case x86_MM2: x86Command = 0x15; break;
	case x86_MM3: x86Command = 0x1D; break;
	case x86_MM4: x86Command = 0x25; break;
	case x86_MM5: x86Command = 0x2D; break;
	case x86_MM6: x86Command = 0x35; break;
	case x86_MM7: x86Command = 0x3D; break;
	}
	PUTDST16(RecompPos,0xe50f);
	PUTDST8(RecompPos, x86Command);
	PUTDSTPTR(RecompPos, Variable);
}
Esempio n. 10
0
CCodeSection::CCodeSection(CCodeBlock * CodeBlock, uint32_t EnterPC, uint32_t ID, bool LinkAllowed) :
    m_BlockInfo(CodeBlock),
    m_SectionID(ID),
    m_EnterPC(EnterPC),
    m_EndPC((uint32_t)-1),
    m_ContinueSection(NULL),
    m_JumpSection(NULL),
    m_EndSection(false),
    m_LinkAllowed(LinkAllowed),
    m_Test(0),
    m_Test2(0),
    m_CompiledLocation(NULL),
    m_InLoop(false),
    m_DelaySlot(false),
    m_RecompilerOps(CodeBlock->RecompilerOps())
{
    CPU_Message("%s: ID %d EnterPC 0x%08X", __FUNCTION__, ID, EnterPC);
    m_RecompilerOps->SetCurrentSection(this);
}
Esempio n. 11
0
void MmxPsllwImmed(int Dest, BYTE Immed) {
	BYTE x86Command = 0;

	CPU_Message("      psllw %s, %i", mmx_Name(Dest), Immed);

	switch (Dest) {
	case x86_MM0: x86Command = 0xF0; break;
	case x86_MM1: x86Command = 0xF1; break;
	case x86_MM2: x86Command = 0xF2; break;
	case x86_MM3: x86Command = 0xF3; break;
	case x86_MM4: x86Command = 0xF4; break;
	case x86_MM5: x86Command = 0xF5; break;
	case x86_MM6: x86Command = 0xF6; break;
	case x86_MM7: x86Command = 0xF7; break;
	}	

	PUTDST16(RecompPos,0x710f);
	PUTDST8(RecompPos, x86Command);
	PUTDST8(RecompPos, Immed);
}
Esempio n. 12
0
void MmxPsrawImmed(int Dest, BYTE Immed) {
	BYTE x86Command = 0;

	CPU_Message("      psraw %s, %i", mmx_Name(Dest), Immed);

	switch (Dest) {
	case x86_MM0: x86Command = 0xE0; break;
	case x86_MM1: x86Command = 0xE1; break;
	case x86_MM2: x86Command = 0xE2; break;
	case x86_MM3: x86Command = 0xE3; break;
	case x86_MM4: x86Command = 0xE4; break;
	case x86_MM5: x86Command = 0xE5; break;
	case x86_MM6: x86Command = 0xE6; break;
	case x86_MM7: x86Command = 0xE7; break;
	}	

	PUTDST16(RecompPos,0x710f);
	PUTDST8(RecompPos, x86Command);
	PUTDST8(RecompPos, Immed);
}
Esempio n. 13
0
void MmxMoveQwordVariableToReg(int Dest, void *Variable, char *VariableName) {
	BYTE x86Command = 0;

	CPU_Message("      movq %s, qword ptr [%s]",mmx_Name(Dest), VariableName);

	switch (Dest) {
	case x86_MM0: x86Command = 0x05; break;
	case x86_MM1: x86Command = 0x0D; break;
	case x86_MM2: x86Command = 0x15; break;
	case x86_MM3: x86Command = 0x1D; break;
	case x86_MM4: x86Command = 0x25; break;
	case x86_MM5: x86Command = 0x2D; break;
	case x86_MM6: x86Command = 0x35; break;
	case x86_MM7: x86Command = 0x3D; break;
	}	

	PUTDST16(RecompPos,0x6f0f);
	PUTDST8(RecompPos, x86Command);
	PUTDSTPTR(RecompPos, Variable);
}
Esempio n. 14
0
void SseMoveAlignedRegToVariable(int sseReg, void *Variable, char *VariableName) {
	BYTE x86Command = 0;

	CPU_Message("      movaps xmmword ptr [%s], %s",VariableName, sse_Name(sseReg));

	switch (sseReg) {
	case x86_XMM0: x86Command = 0x05; break;
	case x86_XMM1: x86Command = 0x0D; break;
	case x86_XMM2: x86Command = 0x15; break;
	case x86_XMM3: x86Command = 0x1D; break;
	case x86_XMM4: x86Command = 0x25; break;
	case x86_XMM5: x86Command = 0x2D; break;
	case x86_XMM6: x86Command = 0x35; break;
	case x86_XMM7: x86Command = 0x3D; break;
	}	

	PUTDST16(RecompPos,0x290f);
	PUTDST8(RecompPos, x86Command);
	PUTDSTPTR(RecompPos, Variable);
}
Esempio n. 15
0
void SseMoveUnalignedVariableToReg(void *Variable, char *VariableName, int sseReg) {
	BYTE x86Command = 0;

	CPU_Message("      movups %s, xmmword ptr [%s]",sse_Name(sseReg), VariableName);

	switch (sseReg) {
	case x86_XMM0: x86Command = 0x05; break;
	case x86_XMM1: x86Command = 0x0D; break;
	case x86_XMM2: x86Command = 0x15; break;
	case x86_XMM3: x86Command = 0x1D; break;
	case x86_XMM4: x86Command = 0x25; break;
	case x86_XMM5: x86Command = 0x2D; break;
	case x86_XMM6: x86Command = 0x35; break;
	case x86_XMM7: x86Command = 0x3D; break;
	}	

	PUTDST16(RecompPos,0x100f);
	PUTDST8(RecompPos, x86Command);
	PUTDSTPTR(RecompPos, Variable);
}
Esempio n. 16
0
void MmxShuffleMemoryToReg(int Dest, void * Variable, char * VariableName, BYTE Immed) {
	BYTE x86Command = 0;

	CPU_Message("      pshufw %s, [%s], %02X", mmx_Name(Dest), VariableName, Immed);

	switch (Dest) {
	case x86_MM0: x86Command = 0x05; break;
	case x86_MM1: x86Command = 0x0D; break;
	case x86_MM2: x86Command = 0x15; break;
	case x86_MM3: x86Command = 0x1D; break;
	case x86_MM4: x86Command = 0x25; break;
	case x86_MM5: x86Command = 0x2D; break;
	case x86_MM6: x86Command = 0x35; break;
	case x86_MM7: x86Command = 0x3D; break;
	}

	PUTDST16(RecompPos,0x700f);
	PUTDST8(RecompPos, x86Command);
	PUTDSTPTR(RecompPos, Variable);
	PUTDST8(RecompPos, Immed);	
}
Esempio n. 17
0
bool CCodeBlock::SetSection(CCodeSection * & Section, CCodeSection * CurrentSection, uint32_t TargetPC, bool LinkAllowed, uint32_t CurrentPC)
{
    if (Section != NULL)
    {
        g_Notify->BreakPoint(__FILE__, __LINE__);
    }

    if (TargetPC >= ((CurrentPC + 0x1000) & 0xFFFFF000))
    {
        return false;
    }

    if (TargetPC < m_EnterSection->m_EnterPC)
    {
        return false;
    }

    if (LinkAllowed)
    {
        if (Section != NULL)
        {
            g_Notify->BreakPoint(__FILE__, __LINE__);
        }
        SectionMap::const_iterator itr = m_SectionMap.find(TargetPC);
        if (itr != m_SectionMap.end())
        {
            Section = itr->second;
            Section->AddParent(CurrentSection);
        }
    }

    if (Section == NULL)
    {
        Section = new CCodeSection(this, TargetPC, m_Sections.size(), LinkAllowed);
        if (Section == NULL)
        {
            g_Notify->BreakPoint(__FILE__, __LINE__);
            return false;
        }
        m_Sections.push_back(Section);
        if (LinkAllowed)
        {
            m_SectionMap.insert(SectionMap::value_type(TargetPC, Section));
        }
        Section->AddParent(CurrentSection);
        if (TargetPC <= CurrentPC && TargetPC != m_VAddrEnter)
        {
            CCodeSection * SplitSection = NULL;
            for (SectionMap::const_iterator itr = m_SectionMap.begin(); itr != m_SectionMap.end(); itr++)
            {
                if (itr->first >= TargetPC)
                {
                    break;
                }
                SplitSection = itr->second;
            }
            if (SplitSection == NULL)
            {
                g_Notify->BreakPoint(__FILE__, __LINE__);
            }
            if (SplitSection->m_EndPC == (uint32_t)-1)
            {
                g_Notify->BreakPoint(__FILE__, __LINE__);
            }
            if (SplitSection->m_EndPC >= TargetPC)
            {
                CPU_Message("%s: Split Section: %d with section: %d", __FUNCTION__, SplitSection->m_SectionID, Section->m_SectionID);
                CCodeSection * BaseSection = Section;
                BaseSection->m_EndPC = SplitSection->m_EndPC;
                BaseSection->SetJumpAddress(SplitSection->m_Jump.JumpPC, SplitSection->m_Jump.TargetPC, SplitSection->m_Jump.PermLoop);
                BaseSection->m_JumpSection = SplitSection->m_JumpSection;
                BaseSection->SetContinueAddress(SplitSection->m_Cont.JumpPC, SplitSection->m_Cont.TargetPC);
                BaseSection->m_ContinueSection = SplitSection->m_ContinueSection;
                BaseSection->m_JumpSection->SwitchParent(SplitSection, BaseSection);
                BaseSection->m_ContinueSection->SwitchParent(SplitSection, BaseSection);
                BaseSection->AddParent(SplitSection);

                SplitSection->m_EndPC = TargetPC - 4;
                SplitSection->m_JumpSection = NULL;
                SplitSection->m_ContinueSection = BaseSection;
                SplitSection->SetContinueAddress(TargetPC - 4, TargetPC);
                SplitSection->SetJumpAddress((uint32_t)-1, (uint32_t)-1, false);
            }
        }
    }
    return true;
}
Esempio n. 18
0
void CCodeSection::UnlinkParent(CCodeSection * Parent, bool ContinueSection)
{
    if (this == NULL)
    {
        return;
    }

    CPU_Message("%s: Section %d Parent: %d ContinueSection = %s", __FUNCTION__, m_SectionID, Parent->m_SectionID, ContinueSection ? "Yes" : "No");
    if (Parent->m_ContinueSection == this && Parent->m_JumpSection == this)
    {
        g_Notify->BreakPoint(__FILE__, __LINE__);
    }

    SECTION_LIST::iterator iter = m_ParentSection.begin();
    while (iter != m_ParentSection.end())
    {
        CCodeSection * ParentIter = *iter;
        if (ParentIter == Parent && (Parent->m_ContinueSection != this || Parent->m_JumpSection != this))
        {
            m_ParentSection.erase(iter);
            iter = m_ParentSection.begin();
        }
        else
        {
            iter++;
        }
    }

    if (ContinueSection && Parent->m_ContinueSection == this)
    {
        Parent->m_ContinueSection = NULL;
    }

    if (!ContinueSection && Parent->m_JumpSection == this)
    {
        Parent->m_JumpSection = NULL;
    }

    bool bRemove = false;
    if (m_ParentSection.size() > 0)
    {
        if (!m_BlockInfo->SectionAccessible(m_SectionID))
        {
            for (SECTION_LIST::iterator iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
            {
                CCodeSection * ParentIter = *iter;
                if (ParentIter->m_ContinueSection == this)
                {
                    if (ParentIter->m_CompiledLocation)
                    {
                        g_Notify->BreakPoint(__FILE__, __LINE__);
                    }
                    ParentIter->m_ContinueSection = NULL;
                }

                if (ParentIter->m_JumpSection == this)
                {
                    if (ParentIter->m_CompiledLocation)
                    {
                        g_Notify->BreakPoint(__FILE__, __LINE__);
                    }
                    ParentIter->m_JumpSection = NULL;
                }
            }
            bRemove = true;
        }
    }
    else
    {
        bRemove = true;
    }
    if (bRemove)
    {
        if (m_JumpSection != NULL)
        {
            m_JumpSection->UnlinkParent(this, false);
        }
        if (m_ContinueSection != NULL)
        {
            m_ContinueSection->UnlinkParent(this, true);
        }
    }
}
Esempio n. 19
0
void MmxEmptyMultimediaState(void) {
	CPU_Message("      emms");
	PUTDST16(RecompPos,0x770f);
}
BOOL WriteToVectorDest2 (DWORD DestReg, int PC, BOOL RecursiveCall) {
	OPCODE RspOp;
	DWORD BranchTarget = 0;
	signed int BranchImmed = 0;
	DWORD JumpTarget = 0;
	BOOL JumpUncond = FALSE;

	int Instruction_State = NextInstruction;

	if (Compiler.bDest == FALSE) return TRUE;

	if (Instruction_State == DELAY_SLOT) { 
		return TRUE; 
	}
	
	do {
		PC += 4;
		if (PC >= 0x1000) { return TRUE; }
		RSP_LW_IMEM(PC, &RspOp.Hex);

		switch (RspOp.op) {

		case RSP_REGIMM:
			switch (RspOp.rt) {
			case RSP_REGIMM_BLTZ:
			case RSP_REGIMM_BGEZ:
			case RSP_REGIMM_BLTZAL:
			case RSP_REGIMM_BGEZAL:
				Instruction_State = DO_DELAY_SLOT;
				break;
			default:
				CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
				return TRUE;
			}
			break;
		case RSP_SPECIAL:
			switch (RspOp.funct) {
			case RSP_SPECIAL_SLL:
			case RSP_SPECIAL_SRL:
			case RSP_SPECIAL_SRA:
			case RSP_SPECIAL_SLLV:
			case RSP_SPECIAL_SRLV:
			case RSP_SPECIAL_SRAV:
			case RSP_SPECIAL_ADD:
			case RSP_SPECIAL_ADDU:
			case RSP_SPECIAL_SUB:
			case RSP_SPECIAL_SUBU:
			case RSP_SPECIAL_AND:
			case RSP_SPECIAL_OR:
			case RSP_SPECIAL_XOR:
			case RSP_SPECIAL_NOR:
			case RSP_SPECIAL_SLT:
			case RSP_SPECIAL_SLTU:
			case RSP_SPECIAL_BREAK:
				break;

			case RSP_SPECIAL_JR:
				Instruction_State = DO_DELAY_SLOT;
				break;

			default:
				CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
				return TRUE;
			}
			break;
		case RSP_J:
		case RSP_JAL:
			if (!JumpTarget) {
				JumpUncond = TRUE;
				JumpTarget = (RspOp.target << 2) & 0xFFC;
			}
			Instruction_State = DO_DELAY_SLOT;
			break;
		case RSP_BEQ:
		case RSP_BNE:
		case RSP_BLEZ:
		case RSP_BGTZ:
			Instruction_State = DO_DELAY_SLOT;
			BranchTarget = (PC + ((short)RspOp.offset << 2) + 4) & 0xFFC;
			BranchImmed = (short)RspOp.offset;
			break;
		case RSP_ADDI:
		case RSP_ADDIU:
		case RSP_SLTI:
		case RSP_SLTIU:
		case RSP_ANDI:
		case RSP_ORI:
		case RSP_XORI:
		case RSP_LUI:
		case RSP_CP0:			
			break;

		case RSP_CP2:
			if ((RspOp.rs & 0x10) != 0) {
				switch (RspOp.funct) {
				case RSP_VECTOR_VMULF:
				case RSP_VECTOR_VMUDL:
				case RSP_VECTOR_VMUDM:
				case RSP_VECTOR_VMUDN:
				case RSP_VECTOR_VMUDH:
				case RSP_VECTOR_VMACF:
				case RSP_VECTOR_VMADL:
				case RSP_VECTOR_VMADM:
				case RSP_VECTOR_VMADN:
				case RSP_VECTOR_VMADH:
				case RSP_VECTOR_VADD:
				case RSP_VECTOR_VADDC:
				case RSP_VECTOR_VSUB:
				case RSP_VECTOR_VSUBC:
				case RSP_VECTOR_VAND:
				case RSP_VECTOR_VOR:
				case RSP_VECTOR_VXOR:
				case RSP_VECTOR_VNXOR:
				case RSP_VECTOR_VABS:
					if (DestReg == RspOp.rd) { return TRUE; }
					if (DestReg == RspOp.rt) { return TRUE; }
					if (DestReg == RspOp.sa) { return FALSE; }
					break;

				case RSP_VECTOR_VMOV:
					if (DestReg == RspOp.rt) { return TRUE; }
					break;

				case RSP_VECTOR_VCR:
				case RSP_VECTOR_VRCP:
				case RSP_VECTOR_VRCPH:
				case RSP_VECTOR_VRSQH:
				case RSP_VECTOR_VCH:
				case RSP_VECTOR_VCL:
					return TRUE;

				case RSP_VECTOR_VMRG:
				case RSP_VECTOR_VLT:
				case RSP_VECTOR_VEQ:
				case RSP_VECTOR_VGE:
					if (DestReg == RspOp.rd) { return TRUE; }
					if (DestReg == RspOp.rt) { return TRUE; }
					if (DestReg == RspOp.sa) { return FALSE; }
					break;
				case RSP_VECTOR_VSAW:
					if (DestReg == RspOp.sa) { return FALSE; }
					break;
				default:
					CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
					return TRUE;
				}
			} else {
				switch (RspOp.rs) {				
				case RSP_COP2_CF:
				case RSP_COP2_CT:
					break;
				case RSP_COP2_MT:
				/*	if (DestReg == RspOp.rd) { return FALSE; } */
					break;
				case RSP_COP2_MF:
					if (DestReg == RspOp.rd) { return TRUE; }
					break;
				default:
					CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
					return TRUE;
				}
			}
			break;
		case RSP_LB:
		case RSP_LH:
		case RSP_LW:
		case RSP_LBU:
		case RSP_LHU:
		case RSP_SB:
		case RSP_SH:
		case RSP_SW:
			break;
		case RSP_LC2:
			switch (RspOp.rd) {
			case RSP_LSC2_SV:
			case RSP_LSC2_DV:
			case RSP_LSC2_RV:
				break;

			case RSP_LSC2_QV:
			case RSP_LSC2_LV:
			case RSP_LSC2_UV:
			case RSP_LSC2_PV:
			case RSP_LSC2_TV:			
				break;

			default:
				CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
				return TRUE;
			}
			break;
		case RSP_SC2:
			switch (RspOp.rd) {
			case RSP_LSC2_BV:
			case RSP_LSC2_SV:
			case RSP_LSC2_LV:
			case RSP_LSC2_DV:
			case RSP_LSC2_QV:
			case RSP_LSC2_RV:
			case RSP_LSC2_PV:
			case RSP_LSC2_UV:
			case RSP_LSC2_HV:
			case RSP_LSC2_FV:
			case RSP_LSC2_WV:
			case RSP_LSC2_TV:
				if (DestReg == RspOp.rt) { return TRUE; }
				break;
			default:
				CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
				return TRUE;
			}
			break;
		default:
			CompilerWarning("Unkown opcode in WriteToVectorDest\n%s",RSPOpcodeName(RspOp.Hex,PC));
			return TRUE;
		}
		switch (Instruction_State) {
		case NORMAL: break;
		case DO_DELAY_SLOT: 
			Instruction_State = DELAY_SLOT;
			break;
		case DELAY_SLOT: 
			if (JumpUncond) {
				PC = JumpTarget - 0x04;
				Instruction_State = NORMAL;
			} else {
				Instruction_State = FINISH_BLOCK; 
			}
			JumpUncond = FALSE;
			break;
		}
	} while (Instruction_State != FINISH_BLOCK);
	
	/***
	** This is a tricky situation because most of the 
	** microcode does loops, so looping back and checking
	** can prove effective, but it's still a branch..
	***/

	if (BranchTarget != 0 && RecursiveCall == FALSE) {
		DWORD BranchTaken, BranchFall;

		/* analysis of branch taken */
		BranchTaken = WriteToVectorDest2(DestReg, BranchTarget - 4, TRUE);
		/* analysis of branch as nop */
		BranchFall = WriteToVectorDest2(DestReg, PC, TRUE);

		if (BranchImmed < 0) {
			if (BranchTaken != FALSE) {
				/*
				** took this back branch and found a place
				** that needs this vector as a source
				**/
				return TRUE;
			} else if (BranchFall == HIT_BRANCH) {
				/* (dlist) risky? the loop ended, hit another branch after loop-back */
			
#if !defined(RSP_SAFE_ANALYSIS)
				CPU_Message("WriteToDest: Backward branch hit, BranchFall = Hit branch (returning FALSE)");
				return FALSE;
#endif

				return TRUE;
			} else {
				/* otherwise this is completely valid */
				return BranchFall;
			}
		} else {	
			if (BranchFall != FALSE) {
				/*
				** took this forward branch and found a place
				** that needs this vector as a source
				**/
				return TRUE;
			} else if (BranchTaken == HIT_BRANCH) {
				/* (dlist) risky? jumped forward, hit another branch */

#if !defined(RSP_SAFE_ANALYSIS)
				CPU_Message("WriteToDest: Forward branch hit, BranchTaken = Hit branch (returning FALSE)");
				return FALSE;
#endif

				return TRUE;
			} else {
				/* otherwise this is completely valid */
				return BranchTaken;
			}
		}
	} else {
		return HIT_BRANCH;
	}
}
Esempio n. 21
0
void CCodeSection::GenerateSectionLinkage()
{
    CCodeSection * TargetSection[] = { m_ContinueSection, m_JumpSection };
    CJumpInfo * JumpInfo[] = { &m_Cont, &m_Jump };
    int i;

    for (i = 0; i < 2; i++)
    {
        if (JumpInfo[i]->LinkLocation == NULL &&
            JumpInfo[i]->FallThrough == false)
        {
            JumpInfo[i]->TargetPC = (uint32_t)-1;
        }
    }

    if ((m_RecompilerOps->GetCurrentPC() & 0xFFC) == 0xFFC)
    {
        g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef legacycode
        //Handle Fall througth
        uint8_t * Jump = NULL;
        for (i = 0; i < 2; i ++)
        {
            if (!JumpInfo[i]->FallThrough) { continue; }
            JumpInfo[i]->FallThrough = false;
            if (JumpInfo[i]->LinkLocation != NULL)
            {
                SetJump32(JumpInfo[i]->LinkLocation,(uint32_t *)*g_RecompPos);
                JumpInfo[i]->LinkLocation = NULL;
                if (JumpInfo[i]->LinkLocation2 != NULL)
                {
                    SetJump32(JumpInfo[i]->LinkLocation2,(uint32_t *)*g_RecompPos);
                    JumpInfo[i]->LinkLocation2 = NULL;
                }
            }
            PushImm32(stdstr_f("0x%08X",JumpInfo[i]->TargetPC).c_str(),JumpInfo[i]->TargetPC);
            if (JumpInfo[(i + 1) & 1]->LinkLocation == NULL) { break; }
            JmpLabel8("FinishBlock",0);
            Jump = *g_RecompPos - 1;
        }
        for (i = 0; i < 2; i ++)
        {
            if (JumpInfo[i]->LinkLocation == NULL) { continue; }
            JumpInfo[i]->FallThrough = false;
            if (JumpInfo[i]->LinkLocation != NULL)
            {
                SetJump32(JumpInfo[i]->LinkLocation,(uint32_t *)*g_RecompPos);
                JumpInfo[i]->LinkLocation = NULL;
                if (JumpInfo[i]->LinkLocation2 != NULL)
                {
                    SetJump32(JumpInfo[i]->LinkLocation2,(uint32_t *)*g_RecompPos);
                    JumpInfo[i]->LinkLocation2 = NULL;
                }
            }
            PushImm32(stdstr_f("0x%08X",JumpInfo[i]->TargetPC).c_str(),JumpInfo[i]->TargetPC);
            if (JumpInfo[(i + 1) & 1]->LinkLocation == NULL) { break; }
            JmpLabel8("FinishBlock",0);
            Jump = *g_RecompPos - 1;
        }
        if (Jump != NULL)
        {
            CPU_Message("      $FinishBlock:");
            SetJump8(Jump,*g_RecompPos);
        }
        //MoveConstToVariable(m_RecompilerOps->GetCurrentPC() + 4,_PROGRAM_COUNTER,"PROGRAM_COUNTER");
        m_RegWorkingSet.WriteBackRegisters();
        m_RecompilerOps->UpdateCounters(m_RegWorkingSet,false,true);
        //		WriteBackRegisters(Section);
        //		if (g_SyncSystem) {
        MoveConstToX86reg((uint32_t)g_BaseSystem,x86_ECX);
        Call_Direct(AddressOf(&CN64System::SyncSystem), "CN64System::SyncSystem");
        //}
        //	MoveConstToVariable(DELAY_SLOT,&m_NextInstruction,"m_NextInstruction");
        PushImm32(stdstr_f("0x%08X",m_RecompilerOps->GetCurrentPC() + 4).c_str(),m_RecompilerOps->GetCurrentPC() + 4);

        // check if there is an existing section

        MoveConstToX86reg((uint32_t)g_Recompiler,x86_ECX);
        Call_Direct(AddressOf(&CRecompiler::CompileDelaySlot), "CRecompiler::CompileDelaySlot");
        JmpDirectReg(x86_EAX);
        ExitCodeBlock();
        return;
#endif
    }

    // Handle Perm Loop
    if (m_RecompilerOps->GetCurrentPC() == m_Jump.TargetPC && (m_Cont.FallThrough == false))
    {
        if (!DelaySlotEffectsJump(m_RecompilerOps->GetCurrentPC()))
        {
            m_RecompilerOps->CompileInPermLoop(m_Jump.RegSet, m_RecompilerOps->GetCurrentPC());
        }
    }
    if (TargetSection[0] != TargetSection[1] || TargetSection[0] == NULL)
    {
        for (i = 0; i < 2; i++)
        {
            if (JumpInfo[i]->LinkLocation == NULL && JumpInfo[i]->FallThrough == false)
            {
                if (TargetSection[i])
                {
                    TargetSection[i]->UnlinkParent(this, i == 0);
                    TargetSection[i] = NULL;
                }
            }
            else if (TargetSection[i] == NULL && JumpInfo[i]->FallThrough)
            {
                m_RecompilerOps->LinkJump(*JumpInfo[i], (uint32_t)-1);
                m_RecompilerOps->CompileExit(JumpInfo[i]->JumpPC, JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet, JumpInfo[i]->ExitReason);
                JumpInfo[i]->FallThrough = false;
            }
            else if (TargetSection[i] != NULL && JumpInfo[i] != NULL)
            {
                if (!JumpInfo[i]->FallThrough) { continue; }
                if (JumpInfo[i]->TargetPC == TargetSection[i]->m_EnterPC) { continue; }
                m_RecompilerOps->LinkJump(*JumpInfo[i], (uint32_t)-1);
                m_RecompilerOps->CompileExit(JumpInfo[i]->JumpPC, JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet, JumpInfo[i]->ExitReason);
                //FreeSection(TargetSection[i],Section);
            }
        }
    }
    else
    {
        if (m_Cont.LinkLocation == NULL && m_Cont.FallThrough == false) { m_ContinueSection = NULL; }
        if (m_Jump.LinkLocation == NULL && m_Jump.FallThrough == false) { m_JumpSection = NULL; }
        if (m_JumpSection == NULL &&  m_ContinueSection == NULL)
        {
            //FreeSection(TargetSection[0],Section);
        }
    }

    TargetSection[0] = m_ContinueSection;
    TargetSection[1] = m_JumpSection;

    for (i = 0; i < 2; i++) {
        if (TargetSection[i] == NULL) { continue; }
        if (!JumpInfo[i]->FallThrough) { continue; }

        if (TargetSection[i]->m_CompiledLocation != NULL)
        {
            JumpInfo[i]->FallThrough = false;
            m_RecompilerOps->LinkJump(*JumpInfo[i], TargetSection[i]->m_SectionID);
            if (JumpInfo[i]->TargetPC <= m_RecompilerOps->GetCurrentPC())
            {
                if (JumpInfo[i]->PermLoop)
                {
                    CPU_Message("PermLoop *** 1");
                    m_RecompilerOps->CompileInPermLoop(JumpInfo[i]->RegSet, JumpInfo[i]->TargetPC);
                }
                else
                {
                    m_RecompilerOps->UpdateCounters(JumpInfo[i]->RegSet, true, true);
                    CPU_Message("CompileSystemCheck 5");
                    m_RecompilerOps->CompileSystemCheck(JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet);
                }
            }
            else
            {
                m_RecompilerOps->UpdateCounters(JumpInfo[i]->RegSet, false, true);
            }

            JumpInfo[i]->RegSet.SetBlockCycleCount(0);
            m_RecompilerOps->SetRegWorkingSet(JumpInfo[i]->RegSet);
            m_RecompilerOps->SyncRegState(TargetSection[i]->m_RegEnter);
            m_RecompilerOps->JumpToSection(TargetSection[i]);
        }
    }

    for (i = 0; i < 2; i++)
    {
        if (TargetSection[i] == NULL) { continue; }
        if (TargetSection[i]->m_ParentSection.empty()) { continue; }
        for (SECTION_LIST::iterator iter = TargetSection[i]->m_ParentSection.begin(); iter != TargetSection[i]->m_ParentSection.end(); iter++)
        {
            CCodeSection * Parent = *iter;

            if (Parent->m_CompiledLocation != NULL) { continue; }
            if (Parent->m_InLoop) { continue; }
            if (JumpInfo[i]->PermLoop)
            {
                CPU_Message("PermLoop *** 2");
                m_RecompilerOps->CompileInPermLoop(JumpInfo[i]->RegSet, JumpInfo[i]->TargetPC);
            }
            if (JumpInfo[i]->FallThrough)
            {
                JumpInfo[i]->FallThrough = false;
                m_RecompilerOps->JumpToUnknown(JumpInfo[i]);
            }
        }
    }

    for (i = 0; i < 2; i++)
    {
        if (JumpInfo[i]->FallThrough)
        {
            if (JumpInfo[i]->TargetPC < m_RecompilerOps->GetCurrentPC())
            {
                m_RecompilerOps->UpdateCounters(JumpInfo[i]->RegSet, true, true);
                CPU_Message("CompileSystemCheck 7");
                m_RecompilerOps->CompileSystemCheck(JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet);
            }
        }
    }

    CPU_Message("====== End of Section %d ======", m_SectionID);

    for (i = 0; i < 2; i++)
    {
        if (JumpInfo[i]->FallThrough && !TargetSection[i]->GenerateNativeCode(m_BlockInfo->NextTest()))
        {
            JumpInfo[i]->FallThrough = false;
            m_RecompilerOps->JumpToUnknown(JumpInfo[i]);
        }
    }

    //CPU_Message("Section %d",m_SectionID);
    for (i = 0; i < 2; i++)
    {
        if (JumpInfo[i]->LinkLocation == NULL) { continue; }
        if (TargetSection[i] == NULL)
        {
            CPU_Message("ExitBlock (from %d):", m_SectionID);
            m_RecompilerOps->LinkJump(*JumpInfo[i], (uint32_t)-1);
            m_RecompilerOps->CompileExit(JumpInfo[i]->JumpPC, JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet, JumpInfo[i]->ExitReason);
            continue;
        }
        if (JumpInfo[i]->TargetPC != TargetSection[i]->m_EnterPC)
        {
            g_Notify->BreakPoint(__FILE__, __LINE__);
        }
        if (TargetSection[i]->m_CompiledLocation == NULL)
        {
            TargetSection[i]->GenerateNativeCode(m_BlockInfo->NextTest());
        }
        else
        {
            stdstr_f Label("Section_%d (from %d):", TargetSection[i]->m_SectionID, m_SectionID);

            CPU_Message(Label.c_str());
            m_RecompilerOps->LinkJump(*JumpInfo[i], (uint32_t)-1);
            m_RecompilerOps->SetRegWorkingSet(JumpInfo[i]->RegSet);
            if (JumpInfo[i]->TargetPC <= JumpInfo[i]->JumpPC)
            {
                m_RecompilerOps->UpdateCounters(JumpInfo[i]->RegSet, true, true);
                if (JumpInfo[i]->PermLoop)
                {
                    CPU_Message("PermLoop *** 3");
                    m_RecompilerOps->CompileInPermLoop(JumpInfo[i]->RegSet, JumpInfo[i]->TargetPC);
                }
                else
                {
                    CPU_Message("CompileSystemCheck 9");
                    m_RecompilerOps->CompileSystemCheck(JumpInfo[i]->TargetPC, JumpInfo[i]->RegSet);
                }
            }
            else
            {
                m_RecompilerOps->UpdateCounters(m_RecompilerOps->GetRegWorkingSet(), false, true);
            }
            m_RecompilerOps->SetRegWorkingSet(JumpInfo[i]->RegSet);
            m_RecompilerOps->SyncRegState(TargetSection[i]->m_RegEnter);
            m_RecompilerOps->JumpToSection(TargetSection[i]);
        }
    }
}
Esempio n. 22
0
bool CCodeBlock::CreateBlockLinkage(CCodeSection * EnterSection)
{
    CCodeSection * CurrentSection = EnterSection;

    CPU_Message("Section %d", CurrentSection->m_SectionID);
    for (uint32_t TestPC = EnterSection->m_EnterPC, EndPC = ((EnterSection->m_EnterPC + 0x1000) & 0xFFFFF000); TestPC <= EndPC; TestPC += 4)
    {
        if (TestPC != EndPC)
        {
            SectionMap::const_iterator itr = m_SectionMap.find(TestPC);
            if (itr != m_SectionMap.end() && CurrentSection != itr->second)
            {
                if (CurrentSection->m_ContinueSection != NULL &&
                    CurrentSection->m_ContinueSection != itr->second)
                {
                    g_Notify->BreakPoint(__FILE__, __LINE__);
                }
                if (CurrentSection->m_ContinueSection == NULL)
                {
                    SetSection(CurrentSection->m_ContinueSection, CurrentSection, TestPC, true, TestPC);
                    CurrentSection->SetContinueAddress(TestPC - 4, TestPC);
                }
                CurrentSection->m_EndPC = TestPC - 4;
                CurrentSection = itr->second;

                CPU_Message("Section %d", CurrentSection->m_SectionID);
                if (EnterSection != m_EnterSection)
                {
                    if (CurrentSection->m_JumpSection != NULL ||
                        CurrentSection->m_ContinueSection != NULL ||
                        CurrentSection->m_EndSection)
                    {
                        break;
                    }
                }
            }
        }
        else
        {
            CurrentSection->m_EndSection = true;
            break;
        }

        bool LikelyBranch, EndBlock, IncludeDelaySlot, PermLoop;
        uint32_t TargetPC, ContinuePC;

        CurrentSection->m_EndPC = TestPC;
        if (!AnalyzeInstruction(TestPC, TargetPC, ContinuePC, LikelyBranch, IncludeDelaySlot, EndBlock, PermLoop))
        {
            g_Notify->BreakPoint(__FILE__, __LINE__);
            return false;
        }

        if (TestPC + 4 == EndPC && IncludeDelaySlot)
        {
            TargetPC = (uint32_t)-1;
            ContinuePC = (uint32_t)-1;
            EndBlock = true;
        }
        if (TargetPC == (uint32_t)-1 && !EndBlock)
        {
            if (ContinuePC != (uint32_t)-1)
            {
                g_Notify->BreakPoint(__FILE__, __LINE__);
            }
            continue;
        }

        if (EndBlock)
        {
            CPU_Message("%s: End Block", __FUNCTION__);
            CurrentSection->m_EndSection = true;
            // find other sections that need compiling
            break;
        }

        if (ContinuePC != (uint32_t)-1)
        {
            CPU_Message("%s: SetContinueAddress TestPC = %X ContinuePC = %X", __FUNCTION__, TestPC, ContinuePC);
            CurrentSection->SetContinueAddress(TestPC, ContinuePC);
            if (!SetSection(CurrentSection->m_ContinueSection, CurrentSection, ContinuePC, true, TestPC))
            {
                ContinuePC = (uint32_t)-1;
            }
        }

        if (LikelyBranch)
        {
            CPU_Message("%s: SetJumpAddress TestPC = %X Target = %X", __FUNCTION__, TestPC, TestPC + 4);
            CurrentSection->SetJumpAddress(TestPC, TestPC + 4, false);
            if (SetSection(CurrentSection->m_JumpSection, CurrentSection, TestPC + 4, false, TestPC))
            {
                bool BranchLikelyBranch, BranchEndBlock, BranchIncludeDelaySlot, BranchPermLoop;
                uint32_t BranchTargetPC, BranchContinuePC;

                CCodeSection * JumpSection = CurrentSection->m_JumpSection;
                if (!AnalyzeInstruction(JumpSection->m_EnterPC, BranchTargetPC, BranchContinuePC, BranchLikelyBranch, BranchIncludeDelaySlot, BranchEndBlock, BranchPermLoop))
                {
                    g_Notify->BreakPoint(__FILE__, __LINE__);
                    return false;
                }

                if (BranchLikelyBranch || BranchIncludeDelaySlot || BranchPermLoop)
                {
                    g_Notify->BreakPoint(__FILE__, __LINE__);
                    return false;
                }

                JumpSection->m_EndPC = TestPC + 4;
                if (BranchEndBlock)
                {
                    CPU_Message("%s: Jump End Block", __FUNCTION__);
                    JumpSection->m_EndSection = true;
                    TargetPC = (uint32_t)-1;
                }
                else
                {
                    JumpSection->SetJumpAddress(TestPC, TargetPC, false);
                }
                JumpSection->SetDelaySlot();
                SetSection(JumpSection->m_JumpSection, JumpSection, TargetPC, true, TestPC);
            }
            else
            {
                g_Notify->BreakPoint(__FILE__, __LINE__);
            }
        }
        else if (TargetPC != ((uint32_t)-1))
        {
            CPU_Message("%s: SetJumpAddress TestPC = %X Target = %X", __FUNCTION__, TestPC, TargetPC);
            CurrentSection->SetJumpAddress(TestPC, TargetPC, PermLoop);
            if (PermLoop || !SetSection(CurrentSection->m_JumpSection, CurrentSection, TargetPC, true, TestPC))
            {
                if (ContinuePC == (uint32_t)-1)
                {
                    CurrentSection->m_EndSection = true;
                }
            }
        }

        TestPC += IncludeDelaySlot ? 8 : 4;

        //Find the next section
        CCodeSection * NewSection = NULL;
        for (SectionMap::const_iterator itr = m_SectionMap.begin(); itr != m_SectionMap.end(); itr++)
        {
            if (CurrentSection->m_JumpSection != NULL ||
                CurrentSection->m_ContinueSection != NULL ||
                CurrentSection->m_EndSection)
            {
                continue;
            }
            NewSection = itr->second;
            break;
        }
        if (NewSection == NULL)
        {
            break;
        }
        if (CurrentSection == NewSection)
        {
            g_Notify->BreakPoint(__FILE__, __LINE__);
        }
        CurrentSection = NewSection;
        if (CurrentSection->m_JumpSection != NULL ||
            CurrentSection->m_ContinueSection != NULL ||
            CurrentSection->m_EndSection)
        {
            break;
        }
        TestPC = CurrentSection->m_EnterPC;
        CPU_Message("a. Section %d", CurrentSection->m_SectionID);
        TestPC -= 4;
    }

    for (SectionMap::iterator itr = m_SectionMap.begin(); itr != m_SectionMap.end(); itr++)
    {
        CCodeSection * Section = itr->second;
        if (Section->m_JumpSection != NULL ||
            Section->m_ContinueSection != NULL ||
            Section->m_EndSection)
        {
            continue;
        }
        if (!CreateBlockLinkage(Section))
        {
            return false;
        }
        break;
    }
    if (CurrentSection->m_EndPC == (uint32_t)-1)
    {
        g_Notify->BreakPoint(__FILE__, __LINE__);
    }
    return true;
}
Esempio n. 23
0
bool CCodeBlock::AnalyzeInstruction(uint32_t PC, uint32_t & TargetPC, uint32_t & ContinuePC, bool & LikelyBranch, bool & IncludeDelaySlot, bool & EndBlock, bool & PermLoop)
{
    TargetPC = (uint32_t)-1;
    ContinuePC = (uint32_t)-1;
    LikelyBranch = false;
    IncludeDelaySlot = false;
    EndBlock = false;
    PermLoop = false;

    OPCODE Command;
    if (!g_MMU->LW_VAddr(PC, Command.Hex))
    {
        g_Notify->BreakPoint(__FILE__, __LINE__);
        return false;
    }

#ifdef _DEBUG
    const char * Name = R4300iOpcodeName(Command.Hex, PC);
    CPU_Message("  0x%08X %s", PC, Name);
#endif
    switch (Command.op)
    {
    case R4300i_SPECIAL:
        switch (Command.funct)
        {
        case R4300i_SPECIAL_SLL:    case R4300i_SPECIAL_SRL:    case R4300i_SPECIAL_SRA:
        case R4300i_SPECIAL_SLLV:   case R4300i_SPECIAL_SRLV:   case R4300i_SPECIAL_SRAV:
        case R4300i_SPECIAL_MFHI:   case R4300i_SPECIAL_MTHI:   case R4300i_SPECIAL_MFLO:
        case R4300i_SPECIAL_MTLO:   case R4300i_SPECIAL_DSLLV:  case R4300i_SPECIAL_DSRLV:
        case R4300i_SPECIAL_DSRAV:  case R4300i_SPECIAL_ADD:    case R4300i_SPECIAL_ADDU:
        case R4300i_SPECIAL_SUB:    case R4300i_SPECIAL_SUBU:   case R4300i_SPECIAL_AND:
        case R4300i_SPECIAL_OR:     case R4300i_SPECIAL_XOR:    case R4300i_SPECIAL_NOR:
        case R4300i_SPECIAL_SLT:    case R4300i_SPECIAL_SLTU:   case R4300i_SPECIAL_DADD:
        case R4300i_SPECIAL_DADDU:  case R4300i_SPECIAL_DSUB:   case R4300i_SPECIAL_DSUBU:
        case R4300i_SPECIAL_DSLL:   case R4300i_SPECIAL_DSRL:   case R4300i_SPECIAL_DSRA:
        case R4300i_SPECIAL_DSLL32: case R4300i_SPECIAL_DSRL32: case R4300i_SPECIAL_DSRA32:
        case R4300i_SPECIAL_MULT:   case R4300i_SPECIAL_MULTU:  case R4300i_SPECIAL_DIV:
        case R4300i_SPECIAL_DIVU:   case R4300i_SPECIAL_DMULT:  case R4300i_SPECIAL_DMULTU:
        case R4300i_SPECIAL_DDIV:   case R4300i_SPECIAL_DDIVU:
            break;
        case R4300i_SPECIAL_JALR:
        case R4300i_SPECIAL_JR:
            EndBlock = true;
            IncludeDelaySlot = true;
            break;
        case R4300i_SPECIAL_SYSCALL:
        case R4300i_SPECIAL_BREAK:
            EndBlock = true;
            break;
        default:
            g_Notify->BreakPoint(__FILE__, __LINE__);
            return false;
        }
        break;
    case R4300i_REGIMM:
        switch (Command.rt)
        {
        case R4300i_REGIMM_BLTZ:
        case R4300i_REGIMM_BLTZAL:
            TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
            if (TargetPC == PC + 8)
            {
                TargetPC = (uint32_t)-1;
            }
            else
            {
                if (TargetPC == PC && !DelaySlotEffectsCompare(PC, Command.rs, 0))
                {
                    PermLoop = true;
                }
                ContinuePC = PC + 8;
                IncludeDelaySlot = true;
            }
            break;
        case R4300i_REGIMM_BGEZ:
        case R4300i_REGIMM_BGEZAL:
            TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
            if (TargetPC == PC + 8)
            {
                TargetPC = (uint32_t)-1;
            }
            else
            {
                if (TargetPC == PC)
                {
                    if (Command.rs == 0)
                    {
                        TargetPC = (uint32_t)-1;
                        EndBlock = true;
                    }
                    else
                    {
                        if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
                        {
                            PermLoop = true;
                        }
                    }
                }
                if (Command.rs != 0)
                {
                    ContinuePC = PC + 8;
                }
                IncludeDelaySlot = true;
            }
            break;
        case R4300i_REGIMM_BLTZL:
        case R4300i_REGIMM_BGEZL:
            TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
            if (TargetPC == PC)
            {
                if (!DelaySlotEffectsCompare(PC, Command.rs, 0))
                {
                    PermLoop = true;
                }
            }
            ContinuePC = PC + 8;
            LikelyBranch = true;
            IncludeDelaySlot = true;
            break;
        default:
            if (Command.Hex == 0x0407000D)
            {
                EndBlock = true;
                break;
            }
            g_Notify->BreakPoint(__FILE__, __LINE__);
            return false;
        }
        break;
    case R4300i_J:
        TargetPC = (PC & 0xF0000000) + (Command.target << 2);
        if (TargetPC == PC)
        {
            PermLoop = true;
        }
        IncludeDelaySlot = true;
        break;
    case R4300i_JAL:
        EndBlock = true;
        IncludeDelaySlot = true;
        break;
    case R4300i_BEQ:
        TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
        if (TargetPC == PC + 8)
        {
            TargetPC = (uint32_t)-1;
        }
        else
        {
            if (Command.rs != 0 || Command.rt != 0)
            {
                ContinuePC = PC + 8;
            }

            if (TargetPC == PC && !DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
            {
                PermLoop = true;
            }
            IncludeDelaySlot = true;
        }
        break;
    case R4300i_BNE:
    case R4300i_BLEZ:
    case R4300i_BGTZ:
        TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
        if (TargetPC == PC + 8)
        {
            TargetPC = (uint32_t)-1;
        }
        else
        {
            if (TargetPC == PC)
            {
                if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
                {
                    PermLoop = true;
                }
            }
            ContinuePC = PC + 8;
            IncludeDelaySlot = true;
        }
        break;
    case R4300i_CP0:
        switch (Command.rs)
        {
        case R4300i_COP0_MT: case R4300i_COP0_MF:
            break;
        default:
            if ((Command.rs & 0x10) != 0)
            {
                switch (Command.funct)
                {
                case R4300i_COP0_CO_TLBR: case R4300i_COP0_CO_TLBWI:
                case R4300i_COP0_CO_TLBWR: case R4300i_COP0_CO_TLBP:
                    break;
                case R4300i_COP0_CO_ERET:
                    EndBlock = true;
                    break;
                default:
                    g_Notify->BreakPoint(__FILE__, __LINE__);
                    return false;
                }
            }
            else
            {
                g_Notify->BreakPoint(__FILE__, __LINE__);
                return false;
            }
            break;
        }
        break;
    case R4300i_CP1:
        switch (Command.fmt)
        {
        case R4300i_COP1_MF:  case R4300i_COP1_DMF: case R4300i_COP1_CF: case R4300i_COP1_MT:
        case R4300i_COP1_DMT: case R4300i_COP1_CT:  case R4300i_COP1_S:  case R4300i_COP1_D:
        case R4300i_COP1_W:   case R4300i_COP1_L:
            break;
        case R4300i_COP1_BC:
            switch (Command.ft) {
            case R4300i_COP1_BC_BCF:
            case R4300i_COP1_BC_BCT:
                TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
                if (TargetPC == PC + 8)
                {
                    TargetPC = (uint32_t)-1;
                }
                else
                {
                    if (TargetPC == PC)
                    {
                        g_Notify->BreakPoint(__FILE__, __LINE__);
                    }
                    ContinuePC = PC + 8;
                    IncludeDelaySlot = true;
                }
                break;
            case R4300i_COP1_BC_BCFL:
            case R4300i_COP1_BC_BCTL:
                TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
                if (TargetPC == PC)
                {
                    g_Notify->BreakPoint(__FILE__, __LINE__);
                }
                ContinuePC = PC + 8;
                LikelyBranch = true;
                IncludeDelaySlot = true;
                break;
            default:
                g_Notify->BreakPoint(__FILE__, __LINE__);
            }
            break;
        default:
            g_Notify->BreakPoint(__FILE__, __LINE__);
            return false;
        }
        break;
    case R4300i_ANDI:  case R4300i_ORI:    case R4300i_XORI:  case R4300i_LUI:
    case R4300i_ADDI:  case R4300i_ADDIU:  case R4300i_SLTI:  case R4300i_SLTIU:
    case R4300i_DADDI: case R4300i_DADDIU: case R4300i_LDL:   case R4300i_LDR:
    case R4300i_LB:    case R4300i_LH:     case R4300i_LWL:   case R4300i_LW:
    case R4300i_LBU:   case R4300i_LHU:    case R4300i_LWR:   case R4300i_LWU:
    case R4300i_SB:    case R4300i_SH:     case R4300i_SWL:   case R4300i_SW:
    case R4300i_SDL:   case R4300i_SDR:    case R4300i_SWR:   case R4300i_CACHE:
    case R4300i_LL:    case R4300i_LWC1:   case R4300i_LDC1:  case R4300i_LD:
    case R4300i_SC:    case R4300i_SWC1:   case R4300i_SDC1:  case R4300i_SD:
        break;
    case R4300i_BEQL:
        TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
        if (TargetPC == PC)
        {
            if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
            {
                PermLoop = true;
            }
        }
        if (Command.rs != 0 || Command.rt != 0)
        {
            ContinuePC = PC + 8;
        }
        IncludeDelaySlot = true;
        LikelyBranch = true;
        break;
    case R4300i_BNEL:
    case R4300i_BLEZL:
    case R4300i_BGTZL:
        TargetPC = PC + ((int16_t)Command.offset << 2) + 4;
        ContinuePC = PC + 8;
        if (TargetPC == PC)
        {
            if (!DelaySlotEffectsCompare(PC, Command.rs, Command.rt))
            {
                PermLoop = true;
            }
        }
        LikelyBranch = true;
        IncludeDelaySlot = true;
        break;
    default:
        if (Command.Hex == 0x7C1C97C0 ||
            Command.Hex == 0xF1F3F5F7)
        {
            EndBlock = true;
            break;
        }
        g_Notify->BreakPoint(__FILE__, __LINE__);
        return false;
    }
    return true;
}
uint32_t WriteToAccum2(int32_t Location, int32_t PC, int32_t RecursiveCall)
{
    RSPOPCODE RspOp;
    uint32_t BranchTarget = 0;
    int32_t BranchImmed = 0;
    uint32_t JumpTarget = 0;
    int32_t JumpUncond = 0;

    int32_t Instruction_State = RSPNextInstruction;

    if (Compiler.bAccum == 0)
	return 1;

    if (Instruction_State == DELAY_SLOT) {
	return 1;
    }

    do {
	PC += 4;
	if (PC >= 0x1000) {
	    return 1;
	}
	RSP_LW_IMEM(PC, &RspOp.Hex);

	switch (RspOp.op) {
	case RSP_REGIMM:
	    switch (RspOp.rt) {
	    case RSP_REGIMM_BLTZ:
	    case RSP_REGIMM_BGEZ:
	    case RSP_REGIMM_BLTZAL:
	    case RSP_REGIMM_BGEZAL:
		Instruction_State = DO_DELAY_SLOT;
		break;
	    default:
		CompilerWarning("Unkown opcode in WriteToAccum\n%s",
				RSPOpcodeName(RspOp.Hex, PC));
		return 1;
	    }
	    break;
	case RSP_SPECIAL:
	    switch (RspOp.funct) {
	    case RSP_SPECIAL_SLL:
	    case RSP_SPECIAL_SRL:
	    case RSP_SPECIAL_SRA:
	    case RSP_SPECIAL_SLLV:
	    case RSP_SPECIAL_SRLV:
	    case RSP_SPECIAL_SRAV:
	    case RSP_SPECIAL_ADD:
	    case RSP_SPECIAL_ADDU:
	    case RSP_SPECIAL_SUB:
	    case RSP_SPECIAL_SUBU:
	    case RSP_SPECIAL_AND:
	    case RSP_SPECIAL_OR:
	    case RSP_SPECIAL_XOR:
	    case RSP_SPECIAL_NOR:
	    case RSP_SPECIAL_SLT:
	    case RSP_SPECIAL_SLTU:
	    case RSP_SPECIAL_BREAK:
		break;

	    case RSP_SPECIAL_JR:
		Instruction_State = DO_DELAY_SLOT;
		break;

	    default:
		CompilerWarning("Unkown opcode in WriteToAccum\n%s",
				RSPOpcodeName(RspOp.Hex, PC));
		return 1;
	    }
	    break;
	case RSP_J:
	case RSP_JAL:
	    if (!JumpTarget) {
		JumpUncond = 1;
		JumpTarget = (RspOp.target << 2) & 0xFFC;
	    }
	    Instruction_State = DO_DELAY_SLOT;
	    break;

	case RSP_BEQ:
	case RSP_BNE:
	case RSP_BLEZ:
	case RSP_BGTZ:
	    Instruction_State = DO_DELAY_SLOT;
	    BranchTarget =
		(PC + ((int16_t) RspOp.offset << 2) + 4) & 0xFFC;
	    BranchImmed = (int16_t) RspOp.offset;
	    break;
	case RSP_ADDI:
	case RSP_ADDIU:
	case RSP_SLTI:
	case RSP_SLTIU:
	case RSP_ANDI:
	case RSP_ORI:
	case RSP_XORI:
	case RSP_LUI:
	case RSP_CP0:
	    break;

	case RSP_CP2:
	    if ((RspOp.rs & 0x10) != 0) {
		switch (RspOp.funct) {
		case RSP_VECTOR_VMULF:
		case RSP_VECTOR_VMUDL:
		case RSP_VECTOR_VMUDM:
		case RSP_VECTOR_VMUDN:
		case RSP_VECTOR_VMUDH:
		    return 0;
		case RSP_VECTOR_VMACF:
		case RSP_VECTOR_VMADL:
		case RSP_VECTOR_VMADM:
		case RSP_VECTOR_VMADN:
		case RSP_VECTOR_VMADH:
		    return 1;
		case RSP_VECTOR_VABS:	// hope this is ok
		case RSP_VECTOR_VADD:
		case RSP_VECTOR_VADDC:
		case RSP_VECTOR_VSUB:
		case RSP_VECTOR_VSUBC:
		case RSP_VECTOR_VAND:
		case RSP_VECTOR_VOR:
		case RSP_VECTOR_VXOR:
		case RSP_VECTOR_VNXOR:
		case RSP_VECTOR_VCR:
		case RSP_VECTOR_VCH:
		case RSP_VECTOR_VCL:
		case RSP_VECTOR_VRCP:
		case RSP_VECTOR_VRCPL:	// hope this is ok
		case RSP_VECTOR_VRCPH:
		case RSP_VECTOR_VRSQL:
		case RSP_VECTOR_VRSQH:	// hope this is ok
		case RSP_VECTOR_VLT:
		case RSP_VECTOR_VEQ:
		case RSP_VECTOR_VGE:
		    if (Location == Low16BitAccum) {
			return 0;
		    }
		    break;

		case RSP_VECTOR_VMOV:
		case RSP_VECTOR_VMRG:
		    break;
		case RSP_VECTOR_VSAW:
		    return 1;
		default:
		    CompilerWarning
			("Unkown opcode in WriteToVectorDest\n%s",
			 RSPOpcodeName(RspOp.Hex, PC));
		    return 1;
		}
	    } else {
		switch (RspOp.rs) {
		case RSP_COP2_CF:
		case RSP_COP2_CT:
		case RSP_COP2_MT:
		case RSP_COP2_MF:
		    break;
		default:
		    CompilerWarning
			("Unkown opcode in WriteToVectorDest\n%s",
			 RSPOpcodeName(RspOp.Hex, PC));
		    return 1;
		}
	    }
	    break;
	case RSP_LB:
	case RSP_LH:
	case RSP_LW:
	case RSP_LBU:
	case RSP_LHU:
	case RSP_SB:
	case RSP_SH:
	case RSP_SW:
	    break;
	case RSP_LC2:
	    switch (RspOp.rd) {
	    case RSP_LSC2_SV:
	    case RSP_LSC2_DV:
	    case RSP_LSC2_RV:
	    case RSP_LSC2_QV:
	    case RSP_LSC2_LV:
	    case RSP_LSC2_UV:
	    case RSP_LSC2_PV:
	    case RSP_LSC2_TV:
		break;
	    default:
		CompilerWarning("Unkown opcode in WriteToAccum\n%s",
				RSPOpcodeName(RspOp.Hex, PC));
		return 1;
	    }
	    break;
	case RSP_SC2:
	    switch (RspOp.rd) {
	    case RSP_LSC2_BV:
	    case RSP_LSC2_SV:
	    case RSP_LSC2_LV:
	    case RSP_LSC2_DV:
	    case RSP_LSC2_QV:
	    case RSP_LSC2_RV:
	    case RSP_LSC2_PV:
	    case RSP_LSC2_UV:
	    case RSP_LSC2_HV:
	    case RSP_LSC2_FV:
	    case RSP_LSC2_WV:
	    case RSP_LSC2_TV:
		break;
	    default:
		CompilerWarning("Unkown opcode in WriteToAccum\n%s",
				RSPOpcodeName(RspOp.Hex, PC));
		return 1;
	    }
	    break;
	default:
	    CompilerWarning("Unkown opcode in WriteToAccum\n%s",
			    RSPOpcodeName(RspOp.Hex, PC));
	    return 1;
	}
	switch (Instruction_State) {
	case NORMAL:
	    break;
	case DO_DELAY_SLOT:
	    Instruction_State = DELAY_SLOT;
	    break;
	case DELAY_SLOT:
	    if (JumpUncond) {
		PC = JumpTarget - 0x04;
		Instruction_State = NORMAL;
	    } else {
		Instruction_State = FINISH_BLOCK;
	    }
	    JumpUncond = 0;
	    break;
	}
    } while (Instruction_State != FINISH_BLOCK);

	/***
	** This is a tricky situation because most of the
	** microcode does loops, so looping back and checking
	** can prove effective, but it's still a branch..
	***/

    if (BranchTarget != 0 && RecursiveCall == 0) {
	uint32_t BranchTaken, BranchFall;

	/* analysis of branch taken */
	BranchTaken = WriteToAccum2(Location, BranchTarget - 4, 1);
	/* analysis of branch as nop */
	BranchFall = WriteToAccum2(Location, PC, 1);

	if (BranchImmed < 0) {
	    if (BranchTaken != 0) {
		/*
		 ** took this back branch and couldnt find a place
		 ** that resets the accum or hit a branch etc
		 **/
		return 1;
	    } else if (BranchFall == HIT_BRANCH) {
		/* risky? the loop ended, hit another branch after loop-back */

#if !defined(RSP_SAFE_ANALYSIS)
		CPU_Message
		    ("WriteToDest: Backward branch hit, BranchFall = Hit branch (returning 0)");
		return 0;
#endif
		return 1;
	    } else {
		/* otherwise this is completely valid */
		return BranchFall;
	    }
	} else {
	    if (BranchFall != 0) {
		/*
		 ** took this forward branch and couldnt find a place
		 ** that resets the accum or hit a branch etc
		 **/
		return 1;
	    } else if (BranchTaken == HIT_BRANCH) {
		/* risky? jumped forward, hit another branch */

#if !defined(RSP_SAFE_ANALYSIS)
		CPU_Message
		    ("WriteToDest: Forward branch hit, BranchTaken = Hit branch (returning 0)");
		return 0;
#endif

		return 1;
	    } else {
		/* otherwise this is completely valid */
		return BranchTaken;
	    }
	}
    } else {
	return HIT_BRANCH;
    }
}
Esempio n. 25
0
BOOL CompareInstructions(DWORD PC, OPCODE * Top, OPCODE * Bottom) {

	OPCODE_INFO info0, info1;
	DWORD InstructionType;

	GetInstructionInfo(PC - 4, Top, &info0);
	GetInstructionInfo(PC, Bottom, &info1);

#ifdef COMPARE_INSTRUCTIONS_VERBOSE
	CPU_Message("Comparing %s (%X)", RSPOpcodeName ( Top->Hex, PC - 4 ), PC - 4);
	CPU_Message("to %s (%X)", RSPOpcodeName ( Bottom->Hex, PC), PC);
#endif

	/* usually branches and such */
	if ((info0.flags & InvalidOpcode) != 0) return FALSE;
	if ((info1.flags & InvalidOpcode) != 0) return FALSE;

	if ((info0.flags & Flag_Instruction) != 0 && (info1.flags & Flag_Instruction) != 0) return FALSE;

	InstructionType = (info0.flags & Instruction_Mask) << 2;
	InstructionType |= info1.flags & Instruction_Mask;
	InstructionType &= 0x0F; /* Paranoia */

	/* 4 bit range, 16 possible combinations */
	switch (InstructionType) {
	/*
	** Detect noop instruction, 7 cases, (see flags) */
	case 0x01: case 0x02: case 0x03: /* First is a noop */
		return TRUE;
	case 0x00:						 /* Both ??? */
	case 0x10: case 0x20: case 0x30: /* Second is a noop */
		return FALSE;

	case 0x06: /* GPR than Vector - 01,10 */
		if ((info0.flags & MemOperation_Mask) != 0 && (info1.flags & MemOperation_Mask) != 0) {
			/* TODO: We have a vector & GPR memory operation */
			return FALSE;
		} else if ((info1.flags & MemOperation_Mask) != 0) {
			/* We have a vector memory operation */
			return (info1.IndexReg == info0.DestReg) ? FALSE : TRUE;
		}
		/* We could have memory or normal gpr instruction here
		** paired with some kind of vector operation
		*/
		return TRUE;
	case 0x0A: /* Vector than Vector - 10,10 */

		/*
		** Check for Vector Store than Vector multiply (VMULF)
		**
		** This basically gives preferences to putting stores
		** as close to the finish of an operation as possible
		*/
		if ((info0.flags & Store_Operation) != 0 && (info1.flags & Accum_Operation) != 0
			&& !(info1.flags & VEC_Accumulate)) { return FALSE; }

		/*
		** Look for loads and than some kind of vector operation
		** that does no accumulating, there is no reason to reorder
		*/
		if ((info0.flags & Load_Operation) != 0 && (info1.flags & Accum_Operation) != 0
			&& !(info1.flags & VEC_Accumulate)) { return FALSE; }

		if ((info0.flags & MemOperation_Mask) != 0 && (info1.flags & MemOperation_Mask) != 0) {
			/*
			** TODO: This is a bitch, its best to leave it alone
			**/
			return FALSE;
		} else if ((info1.flags & MemOperation_Mask) != 0) {
			/* Remember stored reg & loaded reg are the same */
			if (info0.DestReg == info1.DestReg) { return FALSE; }

			if (info1.flags & Load_Operation) {
				if (info0.SourceReg0 == info1.DestReg) { return FALSE; }
				if (info0.SourceReg1 == info1.DestReg) { return FALSE; }
			} else if (info1.flags & Store_Operation) {
				/* It can store source regs */
				return TRUE;
			}

			return TRUE;
		} else if ((info0.flags & MemOperation_Mask) != 0) {
			/* Remember stored reg & loaded reg are the same */
			if (info0.DestReg == info1.DestReg) { return FALSE; }

			if (info0.flags & Load_Operation) {
				if (info1.SourceReg0 == info0.DestReg) { return FALSE; }
				if (info1.SourceReg1 == info0.DestReg) { return FALSE; }
			} else if (info0.flags & Store_Operation) {
				/* It can store source regs */
				return TRUE;
			}

			return TRUE;
		} else if ((info0.flags & VEC_Accumulate) != 0) {
			/*
			** Example:
			**		VMACF
			**		VMUDH or VMADH or VADD
			*/

			return FALSE;
		} else if ((info1.flags & VEC_Accumulate) != 0) {
			/*
			** Example:
			**		VMULF
			**		VMADH
			*/
			
			return FALSE;
		} else {
			/*
			** Example:
			**		VMULF or VADDC
			**		VADD or VMUDH
			*/

			return FALSE;
		}
		break;

	case 0x09: /* Vector than GPR - 10,01 */
		/**********
		** this is where the bias comes into play, otherwise
		** we can sit here all day swapping these 2 types
		***********/
		return FALSE;

	case 0x05: /* GPR than GPR - 01,01 */
	case 0x07: /* GPR than Cop2 - 01, 11 */
	case 0x0D: /* Cop2 than GPR - 11, 01 */
	case 0x0F: /* Cop2 than Cop2 - 11, 11 */
		return FALSE;

	case 0x0B: /* Vector than Cop2 - 10, 11 */
		if (info1.flags & Load_Operation) {
			/* Move To Cop2 (dest) from GPR (source) */
			if (info1.DestReg == info0.DestReg) { return FALSE; }
			if (info1.DestReg == info0.SourceReg0) { return FALSE; }
			if (info1.DestReg == info0.SourceReg1) { return FALSE; }
		} else if (info1.flags & Store_Operation) {
			/* Move From Cop2 (source) to GPR (dest) */
			if (info1.SourceReg0 == info0.DestReg) { return FALSE; }
			if (info1.SourceReg0 == info0.SourceReg0) { return FALSE; }
			if (info1.SourceReg0 == info0.SourceReg1) { return FALSE; }
		} else {
			CompilerWarning("ReOrder: Unhandled Vector than Cop2");
		}
		// we want vectors on top
		return FALSE;

	case 0x0E: /* Cop2 than Vector - 11, 10 */
		if (info0.flags & Load_Operation) {
			/* Move To Cop2 (dest) from GPR (source) */
			if (info0.DestReg == info1.DestReg) { return FALSE; }
			if (info0.DestReg == info1.SourceReg0) { return FALSE; }
			if (info0.DestReg == info1.SourceReg1) { return FALSE; }
		} else if (info0.flags & Store_Operation) {
			/* Move From Cop2 (source) to GPR (dest) */
			if (info0.SourceReg0 == info1.DestReg) { return FALSE; }
			if (info0.SourceReg0 == info1.SourceReg0) { return FALSE; }
			if (info0.SourceReg0 == info1.SourceReg1) { return FALSE; }
			if (info0.DestReg == info1.SourceReg0) { return FALSE; }
		} else {
			CompilerWarning("ReOrder: Unhandled Cop2 than Vector");
		}
		// we want this at the top
		return TRUE;

	default:
		CompilerWarning("ReOrder: Unhandled instruction type: %i", InstructionType);
	}

	return FALSE;
}
Esempio n. 26
0
void CCodeSection::DisplaySectionInformation()
{
    if (m_SectionID == 0)
    {
        return;
    }

    CPU_Message("====== Section %d ======", m_SectionID);
    CPU_Message("Start PC: %X", m_EnterPC);
    if (g_System->bLinkBlocks())
    {
        CPU_Message("End PC: %X", m_EndPC);
    }
    CPU_Message("CompiledLocation: %X", m_CompiledLocation);
    if (g_System->bLinkBlocks() && !m_ParentSection.empty())
    {
        stdstr ParentList;
        for (SECTION_LIST::iterator iter = m_ParentSection.begin(); iter != m_ParentSection.end(); iter++)
        {
            CCodeSection * Parent = *iter;
            if (!ParentList.empty())
            {
                ParentList += ", ";
            }
            ParentList += stdstr_f("%d", Parent->m_SectionID);
        }
        CPU_Message("Number of parents: %d (%s)", m_ParentSection.size(), ParentList.c_str());
    }

    if (g_System->bLinkBlocks())
    {
        CPU_Message("Jump Address: 0x%08X", m_Jump.JumpPC);
        CPU_Message("Jump Target Address: 0x%08X", m_Jump.TargetPC);
        if (m_JumpSection != NULL)
        {
            CPU_Message("Jump Section: %d", m_JumpSection->m_SectionID);
        }
        else
        {
            CPU_Message("Jump Section: None");
        }
        CPU_Message("Continue Address: 0x%08X", m_Cont.JumpPC);
        CPU_Message("Continue Target Address: 0x%08X", m_Cont.TargetPC);
        if (m_ContinueSection != NULL) {
            CPU_Message("Continue Section: %d", m_ContinueSection->m_SectionID);
        }
        else
        {
            CPU_Message("Continue Section: None");
        }
        CPU_Message("In Loop: %s", m_InLoop ? "Yes" : "No");
    }
    CPU_Message("=======================");
}