282 lines
11 KiB
C++
282 lines
11 KiB
C++
/****************************************************************************
|
|
* *
|
|
* Project64 - A Nintendo 64 emulator. *
|
|
* http://www.pj64-emu.com/ *
|
|
* Copyright (C) 2012 Project64. All rights reserved. *
|
|
* *
|
|
* License: *
|
|
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
|
* *
|
|
****************************************************************************/
|
|
#pragma once
|
|
#if defined(__arm__) || defined(_M_ARM)
|
|
#include <Project64-core/N64System/Mips/RegisterClass.h>
|
|
#include <Project64-core/N64System/Recompiler/RecompilerOps.h>
|
|
#include <Project64-core/N64System/Recompiler/Arm/ArmOps.h>
|
|
|
|
class CArmRecompilerOps :
|
|
public CRecompilerOps,
|
|
private CArmOps,
|
|
protected CSystemRegisters
|
|
{
|
|
public:
|
|
CArmRecompilerOps();
|
|
|
|
/************************** Branch functions ************************/
|
|
void Compile_BranchCompare(BRANCH_COMPARE CompareType);
|
|
void Compile_Branch(BRANCH_COMPARE CompareType, BRANCH_TYPE BranchType, bool Link);
|
|
void Compile_BranchLikely(BRANCH_COMPARE CompareType, bool Link);
|
|
void BNE_Compare();
|
|
void BEQ_Compare();
|
|
void BGTZ_Compare();
|
|
void BLEZ_Compare();
|
|
void BLTZ_Compare();
|
|
void BGEZ_Compare();
|
|
void COP1_BCF_Compare();
|
|
void COP1_BCT_Compare();
|
|
|
|
/************************* OpCode functions *************************/
|
|
void J ();
|
|
void JAL ();
|
|
void ADDI ();
|
|
void ADDIU ();
|
|
void SLTI ();
|
|
void SLTIU ();
|
|
void ANDI ();
|
|
void ORI ();
|
|
void XORI ();
|
|
void LUI ();
|
|
void DADDIU ();
|
|
void LDL ();
|
|
void LDR ();
|
|
void LB ();
|
|
void LH ();
|
|
void LWL ();
|
|
void LW ();
|
|
void LBU ();
|
|
void LHU ();
|
|
void LWR ();
|
|
void LWU ();
|
|
void SB ();
|
|
void SH ();
|
|
void SWL ();
|
|
void SW ();
|
|
void SWR ();
|
|
void SDL ();
|
|
void SDR ();
|
|
void CACHE ();
|
|
void LL ();
|
|
void LWC1 ();
|
|
void LDC1 ();
|
|
void LD ();
|
|
void SC ();
|
|
void SWC1 ();
|
|
void SDC1 ();
|
|
void SD ();
|
|
|
|
/********************** R4300i OpCodes: Special **********************/
|
|
void SPECIAL_SLL ();
|
|
void SPECIAL_SRL ();
|
|
void SPECIAL_SRA ();
|
|
void SPECIAL_SLLV ();
|
|
void SPECIAL_SRLV ();
|
|
void SPECIAL_SRAV ();
|
|
void SPECIAL_JR ();
|
|
void SPECIAL_JALR ();
|
|
void SPECIAL_SYSCALL();
|
|
void SPECIAL_MFLO ();
|
|
void SPECIAL_MTLO ();
|
|
void SPECIAL_MFHI ();
|
|
void SPECIAL_MTHI ();
|
|
void SPECIAL_DSLLV ();
|
|
void SPECIAL_DSRLV ();
|
|
void SPECIAL_DSRAV ();
|
|
void SPECIAL_MULT ();
|
|
void SPECIAL_MULTU ();
|
|
void SPECIAL_DIV ();
|
|
void SPECIAL_DIVU ();
|
|
void SPECIAL_DMULT ();
|
|
void SPECIAL_DMULTU ();
|
|
void SPECIAL_DDIV ();
|
|
void SPECIAL_DDIVU ();
|
|
void SPECIAL_ADD ();
|
|
void SPECIAL_ADDU ();
|
|
void SPECIAL_SUB ();
|
|
void SPECIAL_SUBU ();
|
|
void SPECIAL_AND ();
|
|
void SPECIAL_OR ();
|
|
void SPECIAL_XOR ();
|
|
void SPECIAL_NOR ();
|
|
void SPECIAL_SLT ();
|
|
void SPECIAL_SLTU ();
|
|
void SPECIAL_DADD ();
|
|
void SPECIAL_DADDU ();
|
|
void SPECIAL_DSUB ();
|
|
void SPECIAL_DSUBU ();
|
|
void SPECIAL_DSLL ();
|
|
void SPECIAL_DSRL ();
|
|
void SPECIAL_DSRA ();
|
|
void SPECIAL_DSLL32 ();
|
|
void SPECIAL_DSRL32 ();
|
|
void SPECIAL_DSRA32 ();
|
|
|
|
/************************** COP0 functions **************************/
|
|
void COP0_MF ();
|
|
void COP0_MT ();
|
|
|
|
/************************** COP0 CO functions ***********************/
|
|
void COP0_CO_TLBR ();
|
|
void COP0_CO_TLBWI ();
|
|
void COP0_CO_TLBWR ();
|
|
void COP0_CO_TLBP ();
|
|
void COP0_CO_ERET ();
|
|
|
|
/************************** COP1 functions **************************/
|
|
void COP1_MF ();
|
|
void COP1_DMF ();
|
|
void COP1_CF ();
|
|
void COP1_MT ();
|
|
void COP1_DMT ();
|
|
void COP1_CT ();
|
|
|
|
/************************** COP1: S functions ************************/
|
|
void COP1_S_ADD ();
|
|
void COP1_S_SUB ();
|
|
void COP1_S_MUL ();
|
|
void COP1_S_DIV ();
|
|
void COP1_S_ABS ();
|
|
void COP1_S_NEG ();
|
|
void COP1_S_SQRT ();
|
|
void COP1_S_MOV ();
|
|
void COP1_S_ROUND_L ();
|
|
void COP1_S_TRUNC_L ();
|
|
void COP1_S_CEIL_L ();
|
|
void COP1_S_FLOOR_L ();
|
|
void COP1_S_ROUND_W ();
|
|
void COP1_S_TRUNC_W ();
|
|
void COP1_S_CEIL_W ();
|
|
void COP1_S_FLOOR_W ();
|
|
void COP1_S_CVT_D ();
|
|
void COP1_S_CVT_W ();
|
|
void COP1_S_CVT_L ();
|
|
void COP1_S_CMP ();
|
|
|
|
/************************** COP1: D functions ************************/
|
|
void COP1_D_ADD ();
|
|
void COP1_D_SUB ();
|
|
void COP1_D_MUL ();
|
|
void COP1_D_DIV ();
|
|
void COP1_D_ABS ();
|
|
void COP1_D_NEG ();
|
|
void COP1_D_SQRT ();
|
|
void COP1_D_MOV ();
|
|
void COP1_D_ROUND_L ();
|
|
void COP1_D_TRUNC_L ();
|
|
void COP1_D_CEIL_L ();
|
|
void COP1_D_FLOOR_L ();
|
|
void COP1_D_ROUND_W ();
|
|
void COP1_D_TRUNC_W ();
|
|
void COP1_D_CEIL_W ();
|
|
void COP1_D_FLOOR_W ();
|
|
void COP1_D_CVT_S ();
|
|
void COP1_D_CVT_W ();
|
|
void COP1_D_CVT_L ();
|
|
void COP1_D_CMP ();
|
|
|
|
/************************** COP1: W functions ************************/
|
|
void COP1_W_CVT_S ();
|
|
void COP1_W_CVT_D ();
|
|
|
|
/************************** COP1: L functions ************************/
|
|
void COP1_L_CVT_S ();
|
|
void COP1_L_CVT_D ();
|
|
|
|
/************************** Other functions **************************/
|
|
void UnknownOpcode ();
|
|
|
|
private:
|
|
void EnterCodeBlock();
|
|
void ExitCodeBlock();
|
|
void CompileExitCode();
|
|
void CompileCop1Test();
|
|
void CompileInPermLoop(CRegInfo & RegSet, uint32_t ProgramCounter);
|
|
void OutputRegisterState(const CRegInfo & SyncTo, const CRegInfo & CurrentSet) const;
|
|
void SyncRegState(const CRegInfo & SyncTo);
|
|
bool SetupRegisterForLoop(CCodeBlock * BlockInfo, const CRegInfo & RegSet);
|
|
CRegInfo & GetRegWorkingSet(void);
|
|
void SetRegWorkingSet(const CRegInfo & RegInfo);
|
|
bool InheritParentInfo();
|
|
void LinkJump(CJumpInfo & JumpInfo, uint32_t SectionID = -1, uint32_t FromSectionID = -1);
|
|
void JumpToSection( CCodeSection * Section);
|
|
void JumpToUnknown(CJumpInfo * JumpInfo);
|
|
void SetCurrentPC(uint32_t ProgramCounter);
|
|
uint32_t GetCurrentPC(void);
|
|
void SetCurrentSection(CCodeSection * section);
|
|
void SetNextStepType(STEP_TYPE StepType);
|
|
STEP_TYPE GetNextStepType( void );
|
|
const OPCODE & GetOpcode ( void ) const;
|
|
void PreCompileOpcode(void);
|
|
void PostCompileOpcode ( void );
|
|
void CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo &ExitRegSet, CExitInfo::EXIT_REASON reason);
|
|
void CompileExit(uint32_t JumpPC, uint32_t TargetPC, CRegInfo &ExitRegSet, CExitInfo::EXIT_REASON reason, CArmOps::ArmCompareType CompareType);
|
|
static void UpdateSyncCPU(CRegInfo & RegSet, uint32_t Cycles);
|
|
void UpdateCounters(CRegInfo & RegSet, bool CheckTimer, bool ClearValues = false);
|
|
void CompileSystemCheck(uint32_t TargetPC, const CRegInfo & RegSet);
|
|
void CompileReadTLBMiss(ArmReg AddressReg, ArmReg LookUpReg);
|
|
void CompileWriteTLBMiss(ArmReg AddressReg, ArmReg LookUpReg);
|
|
|
|
/********* Helper Functions *********/
|
|
typedef CRegInfo::REG_STATE REG_STATE;
|
|
|
|
static inline REG_STATE GetMipsRegState(int32_t Reg) { return m_RegWorkingSet.GetMipsRegState(Reg); }
|
|
static inline uint64_t GetMipsReg(int32_t Reg) { return m_RegWorkingSet.GetMipsReg(Reg); }
|
|
static inline uint32_t GetMipsRegLo(int32_t Reg) { return m_RegWorkingSet.GetMipsRegLo(Reg); }
|
|
static inline int32_t GetMipsRegLo_S(int32_t Reg) { return m_RegWorkingSet.GetMipsRegLo_S(Reg); }
|
|
static inline uint32_t GetMipsRegHi(int32_t Reg) { return m_RegWorkingSet.GetMipsRegHi(Reg); }
|
|
static inline int32_t GetMipsRegHi_S(int32_t Reg) { return m_RegWorkingSet.GetMipsRegHi_S(Reg); }
|
|
static inline ArmReg GetMipsRegMapLo(int32_t Reg) { return m_RegWorkingSet.GetMipsRegMapLo(Reg); }
|
|
static inline ArmReg GetMipsRegMapHi(int32_t Reg) { return m_RegWorkingSet.GetMipsRegMapHi(Reg); }
|
|
|
|
static inline bool IsKnown(int32_t Reg) { return m_RegWorkingSet.IsKnown(Reg); }
|
|
static inline bool IsUnknown(int32_t Reg) { return m_RegWorkingSet.IsUnknown(Reg); }
|
|
static inline bool IsMapped(int32_t Reg) { return m_RegWorkingSet.IsMapped(Reg); }
|
|
static inline bool IsConst(int32_t Reg) { return m_RegWorkingSet.IsConst(Reg); }
|
|
static inline bool IsSigned(int32_t Reg) { return m_RegWorkingSet.IsSigned(Reg); }
|
|
static inline bool IsUnsigned(int32_t Reg) { return m_RegWorkingSet.IsUnsigned(Reg); }
|
|
static inline bool Is32Bit(int32_t Reg) { return m_RegWorkingSet.Is32Bit(Reg); }
|
|
static inline bool Is64Bit(int32_t Reg) { return m_RegWorkingSet.Is64Bit(Reg); }
|
|
static inline bool Is32BitMapped(int32_t Reg) { return m_RegWorkingSet.Is32BitMapped(Reg); }
|
|
static inline bool Is64BitMapped(int32_t Reg) { return m_RegWorkingSet.Is64BitMapped(Reg); }
|
|
static inline void Map_GPR_32bit(int32_t Reg, bool SignValue, int32_t MipsRegToLoad) { m_RegWorkingSet.Map_GPR_32bit(Reg, SignValue, MipsRegToLoad); }
|
|
static inline void Map_GPR_64bit(int32_t Reg, int32_t MipsRegToLoad) { m_RegWorkingSet.Map_GPR_64bit(Reg, MipsRegToLoad); }
|
|
static inline void UnMap_GPR(uint32_t Reg, bool WriteBackValue){ m_RegWorkingSet.UnMap_GPR(Reg, WriteBackValue); }
|
|
static inline void WriteBack_GPR(uint32_t Reg, bool Unmapping){ m_RegWorkingSet.WriteBack_GPR(Reg, Unmapping); }
|
|
static inline ArmReg Map_TempReg(ArmReg Reg, int32_t MipsReg, bool LoadHiWord) { return m_RegWorkingSet.Map_TempReg(Reg, MipsReg, LoadHiWord); }
|
|
static inline ArmReg Map_Variable(CArmRegInfo::VARIABLE_MAPPED variable, ArmReg Reg = Arm_Any) { return m_RegWorkingSet.Map_Variable(variable, Reg); }
|
|
|
|
static inline void ResetRegProtection() { m_RegWorkingSet.ResetRegProtection(); }
|
|
static inline void FixRoundModel(CRegInfo::FPU_ROUND RoundMethod) { m_RegWorkingSet.FixRoundModel(RoundMethod); }
|
|
|
|
static inline void ProtectGPR(uint32_t Reg) { m_RegWorkingSet.ProtectGPR(Reg); }
|
|
static inline void UnProtectGPR(uint32_t Reg) { m_RegWorkingSet.UnProtectGPR(Reg); }
|
|
static inline bool UnMap_ArmReg(ArmReg Reg) { return m_RegWorkingSet.UnMap_ArmReg(Reg); }
|
|
|
|
void SW(bool bCheckLLbit);
|
|
void SW_Const(uint32_t Value, uint32_t VAddr);
|
|
void SW_Register(ArmReg Reg, uint32_t VAddr);
|
|
void LW(bool ResultSigned, bool bRecordLLBit);
|
|
void LB_KnownAddress(ArmReg Reg, uint32_t VAddr, bool SignExtend);
|
|
void LW_KnownAddress(ArmReg Reg, uint32_t VAddr);
|
|
void CompileInterpterCall (void * Function, const char * FunctionName);
|
|
void OverflowDelaySlot(bool TestTimer);
|
|
|
|
EXIT_LIST m_ExitInfo;
|
|
STEP_TYPE m_NextInstruction;
|
|
uint32_t m_CompilePC;
|
|
OPCODE m_Opcode;
|
|
CCodeSection * m_Section;
|
|
|
|
static uint32_t m_TempValue;
|
|
};
|
|
|
|
#endif |