mirror of https://github.com/PCSX2/pcsx2.git
Cleanups to iCore.cpp and other Dynarec code. Moved BASEBLOCKEX into its own files/headers.
git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@617 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
parent
46f5bb51e9
commit
cb70542e4c
|
@ -34,6 +34,7 @@
|
|||
#include "VU.h"
|
||||
#include "iCore.h"
|
||||
#include "iVUzerorec.h"
|
||||
#include "BaseblockEx.h" // for debuild block dumping (which may or may not work anymore?)
|
||||
|
||||
#include "GS.h"
|
||||
#include "COP0.h"
|
||||
|
|
|
@ -119,7 +119,6 @@ int AddPatch(int Mode, int Place, int Address, int Size, u64 data);
|
|||
|
||||
namespace Dynarec {
|
||||
extern void SetFastMemory(int); // iR5900LoadStore.c
|
||||
extern void SetVUNanMemory(int); // iVUmicro.c
|
||||
extern void SetVUNanMode(int mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -2176,6 +2176,14 @@
|
|||
<Filter
|
||||
Name="Ps2"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\x86\BaseblockEx.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\BaseblockEx.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="EE"
|
||||
>
|
||||
|
@ -2421,6 +2429,14 @@
|
|||
<File
|
||||
RelativePath="..\..\x86\ix86-32\iR5900-32.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Devel vtlb|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AssemblerOutput="4"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86-32\iR5900Arit.cpp"
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "PS2Etypes.h"
|
||||
|
||||
#include "System.h"
|
||||
#include "R5900.h"
|
||||
#include "Vif.h"
|
||||
|
@ -1008,39 +1006,6 @@ void _freeXMMregs()
|
|||
}
|
||||
}
|
||||
|
||||
// PSX
|
||||
void _psxMoveGPRtoR(x86IntRegType to, int fromgpr)
|
||||
{
|
||||
if( PSX_IS_CONST1(fromgpr) )
|
||||
MOV32ItoR( to, g_psxConstRegs[fromgpr] );
|
||||
else {
|
||||
// check x86
|
||||
MOV32MtoR(to, (uptr)&psxRegs.GPR.r[ fromgpr ] );
|
||||
}
|
||||
}
|
||||
|
||||
void _psxMoveGPRtoM(u32 to, int fromgpr)
|
||||
{
|
||||
if( PSX_IS_CONST1(fromgpr) )
|
||||
MOV32ItoM( to, g_psxConstRegs[fromgpr] );
|
||||
else {
|
||||
// check x86
|
||||
MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[ fromgpr ] );
|
||||
MOV32RtoM(to, EAX );
|
||||
}
|
||||
}
|
||||
|
||||
void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr)
|
||||
{
|
||||
if( PSX_IS_CONST1(fromgpr) )
|
||||
MOV32ItoRmOffset( to, g_psxConstRegs[fromgpr], 0 );
|
||||
else {
|
||||
// check x86
|
||||
MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[ fromgpr ] );
|
||||
MOV32RtoRm(to, EAX );
|
||||
}
|
||||
}
|
||||
|
||||
PCSX2_ALIGNED16(u32 s_zeros[4]) = {0};
|
||||
int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy)
|
||||
{
|
||||
|
@ -1177,145 +1142,6 @@ void SetMMXstate() {
|
|||
x86FpuState = MMX_STATE;
|
||||
}
|
||||
|
||||
// Writebacks //
|
||||
void _recClearWritebacks()
|
||||
{
|
||||
}
|
||||
|
||||
void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent)
|
||||
{
|
||||
}
|
||||
|
||||
EEINSTWRITEBACK* _recCheckWriteBack(int cycle)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct BASEBLOCKS
|
||||
{
|
||||
// 0 - ee, 1 - iop
|
||||
void Add(BASEBLOCKEX*);
|
||||
void Remove(BASEBLOCKEX*);
|
||||
int Get(u32 startpc);
|
||||
void Reset();
|
||||
|
||||
BASEBLOCKEX** GetAll(int* pnum);
|
||||
|
||||
vector<BASEBLOCKEX*> blocks;
|
||||
};
|
||||
|
||||
void BASEBLOCKS::Add(BASEBLOCKEX* pex)
|
||||
{
|
||||
assert( pex != NULL );
|
||||
|
||||
switch(blocks.size()) {
|
||||
case 0:
|
||||
blocks.push_back(pex);
|
||||
return;
|
||||
case 1:
|
||||
assert( blocks.front()->startpc != pex->startpc );
|
||||
|
||||
if( blocks.front()->startpc < pex->startpc ) {
|
||||
blocks.push_back(pex);
|
||||
}
|
||||
else blocks.insert(blocks.begin(), pex);
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
{
|
||||
int imin = 0, imax = blocks.size(), imid;
|
||||
|
||||
while(imin < imax) {
|
||||
imid = (imin+imax)>>1;
|
||||
|
||||
if( blocks[imid]->startpc > pex->startpc ) imax = imid;
|
||||
else imin = imid+1;
|
||||
}
|
||||
|
||||
assert( imin == blocks.size() || blocks[imin]->startpc > pex->startpc );
|
||||
if( imin > 0 ) assert( blocks[imin-1]->startpc < pex->startpc );
|
||||
blocks.insert(blocks.begin()+imin, pex);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BASEBLOCKS::Get(u32 startpc)
|
||||
{
|
||||
switch(blocks.size()) {
|
||||
case 1:
|
||||
return 0;
|
||||
case 2:
|
||||
return blocks.front()->startpc < startpc;
|
||||
|
||||
default:
|
||||
{
|
||||
int imin = 0, imax = blocks.size()-1, imid;
|
||||
|
||||
while(imin < imax) {
|
||||
imid = (imin+imax)>>1;
|
||||
|
||||
if( blocks[imid]->startpc > startpc ) imax = imid;
|
||||
else if( blocks[imid]->startpc == startpc ) return imid;
|
||||
else imin = imid+1;
|
||||
}
|
||||
|
||||
assert( blocks[imin]->startpc == startpc );
|
||||
return imin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BASEBLOCKS::Remove(BASEBLOCKEX* pex)
|
||||
{
|
||||
assert( pex != NULL );
|
||||
int i = Get(pex->startpc);
|
||||
assert( blocks[i] == pex );
|
||||
blocks.erase(blocks.begin()+i);
|
||||
}
|
||||
|
||||
void BASEBLOCKS::Reset()
|
||||
{
|
||||
blocks.resize(0);
|
||||
blocks.reserve(512);
|
||||
}
|
||||
|
||||
BASEBLOCKEX** BASEBLOCKS::GetAll(int* pnum)
|
||||
{
|
||||
assert( pnum != NULL );
|
||||
*pnum = blocks.size();
|
||||
return &blocks[0];
|
||||
}
|
||||
|
||||
static BASEBLOCKS s_vecBaseBlocksEx[2];
|
||||
|
||||
void AddBaseBlockEx(BASEBLOCKEX* pex, int cpu)
|
||||
{
|
||||
s_vecBaseBlocksEx[cpu].Add(pex);
|
||||
}
|
||||
|
||||
BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu)
|
||||
{
|
||||
return s_vecBaseBlocksEx[cpu].blocks[s_vecBaseBlocksEx[cpu].Get(startpc)];
|
||||
}
|
||||
|
||||
void RemoveBaseBlockEx(BASEBLOCKEX* pex, int cpu)
|
||||
{
|
||||
s_vecBaseBlocksEx[cpu].Remove(pex);
|
||||
}
|
||||
|
||||
void ResetBaseBlockEx(int cpu)
|
||||
{
|
||||
s_vecBaseBlocksEx[cpu].Reset();
|
||||
}
|
||||
|
||||
BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu)
|
||||
{
|
||||
return s_vecBaseBlocksEx[cpu].GetAll(pnum);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//#include "R3000A.h"
|
||||
//#include "PsxCounters.h"
|
||||
|
|
|
@ -22,41 +22,70 @@
|
|||
#include "ix86/ix86.h"
|
||||
#include "iVUmicro.h"
|
||||
|
||||
// Namespace Note : Dyanmic recompiler tools used by EE, IOP, and PS2 hardware.
|
||||
// Underneath this namespace thenare Dynarec::R5900, Dynarec::R3000a, etc. for each
|
||||
// of the items specific to those CPUs (those are defined in other headers).
|
||||
// Namespace Note : iCore32 contains all of the Register Allocation logic, in addition to a handful
|
||||
// of utility functions for emitting frequent code.
|
||||
|
||||
namespace Dynarec
|
||||
{
|
||||
// used to keep block information
|
||||
#define BLOCKTYPE_STARTPC 4 // startpc offset
|
||||
#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Shared Register allocation flags (apply to X86, XMM, MMX, etc).
|
||||
|
||||
struct BASEBLOCK
|
||||
{
|
||||
u32 pFnptr : 28;
|
||||
u32 uType : 4;
|
||||
u32 startpc;
|
||||
};
|
||||
#define MODE_READ 1
|
||||
#define MODE_WRITE 2
|
||||
#define MODE_READHALF 4 // read only low 64 bits
|
||||
#define MODE_VUXY 0x8 // vector only has xy valid (real zw are in mem), not the same as MODE_READHALF
|
||||
#define MODE_VUZ 0x10 // z only doesn't work for now
|
||||
#define MODE_VUXYZ (MODE_VUZ|MODE_VUXY) // vector only has xyz valid (real w is in memory)
|
||||
#define MODE_NOFLUSH 0x20 // can't flush reg to mem
|
||||
#define MODE_NOFRAME 0x40 // when allocating x86regs, don't use ebp reg
|
||||
#define MODE_8BITREG 0x80 // when allocating x86regs, use only eax, ecx, edx, and ebx
|
||||
|
||||
C_ASSERT( sizeof(BASEBLOCK) == 8 );
|
||||
#define PROCESS_EE_MMX 0x01
|
||||
#define PROCESS_EE_XMM 0x02
|
||||
|
||||
// extra block info (only valid for start of fn)
|
||||
struct BASEBLOCKEX
|
||||
{
|
||||
u16 size; // size in dwords
|
||||
u16 dummy;
|
||||
u32 startpc; // for debugging?
|
||||
// currently only used in FPU
|
||||
#define PROCESS_EE_S 0x04 // S is valid, otherwise take from mem
|
||||
#define PROCESS_EE_T 0x08 // T is valid, otherwise take from mem
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
u32 visited; // number of times called
|
||||
LARGE_INTEGER ltime; // regs it assumes to have set already
|
||||
#endif
|
||||
// not used in VU recs
|
||||
#define PROCESS_EE_MODEWRITES 0x10 // if s is a reg, set if not in cpuRegs
|
||||
#define PROCESS_EE_MODEWRITET 0x20 // if t is a reg, set if not in cpuRegs
|
||||
#define PROCESS_EE_LO 0x40 // lo reg is valid
|
||||
#define PROCESS_EE_HI 0x80 // hi reg is valid
|
||||
#define PROCESS_EE_ACC 0x40 // acc reg is valid
|
||||
|
||||
};
|
||||
// used in VU recs
|
||||
#define PROCESS_VU_UPDATEFLAGS 0x10
|
||||
#define PROCESS_VU_SUPER 0x40 // set if using supervu recompilation
|
||||
#define PROCESS_VU_COP2 0x80 // simple cop2
|
||||
|
||||
#define GET_BLOCKTYPE(b) ((b)->Type)
|
||||
#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff)))
|
||||
#define EEREC_S (((info)>>8)&0xf)
|
||||
#define EEREC_T (((info)>>12)&0xf)
|
||||
#define EEREC_D (((info)>>16)&0xf)
|
||||
#define EEREC_LO (((info)>>20)&0xf)
|
||||
#define EEREC_HI (((info)>>24)&0xf)
|
||||
#define EEREC_ACC (((info)>>20)&0xf)
|
||||
#define EEREC_TEMP (((info)>>24)&0xf)
|
||||
#define VUREC_FMAC ((info)&0x80000000)
|
||||
|
||||
#define PROCESS_EE_SET_S(reg) ((reg)<<8)
|
||||
#define PROCESS_EE_SET_T(reg) ((reg)<<12)
|
||||
#define PROCESS_EE_SET_D(reg) ((reg)<<16)
|
||||
#define PROCESS_EE_SET_LO(reg) ((reg)<<20)
|
||||
#define PROCESS_EE_SET_HI(reg) ((reg)<<24)
|
||||
#define PROCESS_EE_SET_ACC(reg) ((reg)<<20)
|
||||
|
||||
#define PROCESS_VU_SET_ACC(reg) PROCESS_EE_SET_ACC(reg)
|
||||
#define PROCESS_VU_SET_TEMP(reg) ((reg)<<24)
|
||||
|
||||
#define PROCESS_VU_SET_FMAC() 0x80000000
|
||||
|
||||
// special info not related to above flags
|
||||
#define PROCESS_CONSTS 1
|
||||
#define PROCESS_CONSTT 2
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// X86 (32-bit) Register Allocation Tools
|
||||
|
||||
#define X86TYPE_TEMP 0
|
||||
#define X86TYPE_GPR 1
|
||||
|
@ -106,56 +135,8 @@ void _flushCachedRegs();
|
|||
void _flushConstRegs();
|
||||
void _flushConstReg(int reg);
|
||||
|
||||
// see MEM_X defines for argX format
|
||||
extern void _callPushArg(u32 arg, uptr argmem); /// X86ARG is ignored for 32bit recs
|
||||
extern void _callFunctionArg1(uptr fn, u32 arg1, uptr arg1mem);
|
||||
extern void _callFunctionArg2(uptr fn, u32 arg1, u32 arg2, uptr arg1mem, uptr arg2mem);
|
||||
extern void _callFunctionArg3(uptr fn, u32 arg1, u32 arg2, u32 arg3, uptr arg1mem, uptr arg2mem, uptr arg3mem);
|
||||
|
||||
// return type: 0 - const, 1 - mmx, 2 - xmm
|
||||
#define PROCESS_EE_MMX 0x01
|
||||
#define PROCESS_EE_XMM 0x02
|
||||
|
||||
// currently only used in FPU
|
||||
#define PROCESS_EE_S 0x04 // S is valid, otherwise take from mem
|
||||
#define PROCESS_EE_T 0x08 // T is valid, otherwise take from mem
|
||||
|
||||
// not used in VU recs
|
||||
#define PROCESS_EE_MODEWRITES 0x10 // if s is a reg, set if not in cpuRegs
|
||||
#define PROCESS_EE_MODEWRITET 0x20 // if t is a reg, set if not in cpuRegs
|
||||
#define PROCESS_EE_LO 0x40 // lo reg is valid
|
||||
#define PROCESS_EE_HI 0x80 // hi reg is valid
|
||||
#define PROCESS_EE_ACC 0x40 // acc reg is valid
|
||||
|
||||
// used in VU recs
|
||||
#define PROCESS_VU_UPDATEFLAGS 0x10
|
||||
#define PROCESS_VU_SUPER 0x40 // set if using supervu recompilation
|
||||
#define PROCESS_VU_COP2 0x80 // simple cop2
|
||||
|
||||
#define EEREC_S (((info)>>8)&0xf)
|
||||
#define EEREC_T (((info)>>12)&0xf)
|
||||
#define EEREC_D (((info)>>16)&0xf)
|
||||
#define EEREC_LO (((info)>>20)&0xf)
|
||||
#define EEREC_HI (((info)>>24)&0xf)
|
||||
#define EEREC_ACC (((info)>>20)&0xf)
|
||||
#define EEREC_TEMP (((info)>>24)&0xf)
|
||||
#define VUREC_FMAC ((info)&0x80000000)
|
||||
|
||||
#define PROCESS_EE_SET_S(reg) ((reg)<<8)
|
||||
#define PROCESS_EE_SET_T(reg) ((reg)<<12)
|
||||
#define PROCESS_EE_SET_D(reg) ((reg)<<16)
|
||||
#define PROCESS_EE_SET_LO(reg) ((reg)<<20)
|
||||
#define PROCESS_EE_SET_HI(reg) ((reg)<<24)
|
||||
#define PROCESS_EE_SET_ACC(reg) ((reg)<<20)
|
||||
|
||||
#define PROCESS_VU_SET_ACC(reg) PROCESS_EE_SET_ACC(reg)
|
||||
#define PROCESS_VU_SET_TEMP(reg) ((reg)<<24)
|
||||
|
||||
#define PROCESS_VU_SET_FMAC() 0x80000000
|
||||
|
||||
// special info not related to above flags
|
||||
#define PROCESS_CONSTS 1
|
||||
#define PROCESS_CONSTT 2
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XMM (128-bit) Register Allocation Tools
|
||||
|
||||
#define XMM_CONV_VU(VU) (VU==&VU1)
|
||||
|
||||
|
@ -207,49 +188,8 @@ u8 _hasFreeXMMreg();
|
|||
void _freeXMMregs();
|
||||
int _getNumXMMwrite();
|
||||
|
||||
// Constants used for controlling iFlushCall, _psxFlushCall
|
||||
#define FLUSH_CACHED_REGS 1
|
||||
#define FLUSH_FLUSH_XMM 2
|
||||
#define FLUSH_FREE_XMM 4 // both flushes and frees
|
||||
#define FLUSH_FLUSH_MMX 8
|
||||
#define FLUSH_FREE_MMX 16 // both flushes and frees
|
||||
#define FLUSH_FLUSH_ALLX86 32 // flush x86
|
||||
#define FLUSH_FREE_TEMPX86 64 // flush and free temporary x86 regs
|
||||
#define FLUSH_FREE_ALLX86 128 // free all x86 regs
|
||||
#define FLUSH_FREE_VU0 0x100 // free all vu0 related regs
|
||||
|
||||
// Flushing vs. Freeing, as understood by Air (I could be wrong still....)
|
||||
|
||||
// "Freeing" registers means that the contents of the registers are flushed to memory.
|
||||
// This is good for any sort of C code function that plans to modify the actual
|
||||
// registers. When the Recs resume, they'll reload the registers with values saved
|
||||
// as needed. (similar to a "FreezeXMMRegs")
|
||||
|
||||
// "Flushing" means that in addition to the standard free (which is actually a flush)
|
||||
// the register allocations are additionally wiped. This should only be necessary if
|
||||
// the code being called is going to modify register allocations -- ie, be doing
|
||||
// some kind of recompiling of its own.
|
||||
|
||||
#define FLUSH_EVERYTHING 0xfff
|
||||
// no freeing, used when callee won't destroy mmx/xmm regs
|
||||
#define FLUSH_NODESTROY (FLUSH_CACHED_REGS|FLUSH_FLUSH_XMM|FLUSH_FLUSH_MMX|FLUSH_FLUSH_ALLX86)
|
||||
// used when regs aren't going to be changed be callee
|
||||
#define FLUSH_NOCONST (FLUSH_FREE_XMM|FLUSH_FREE_MMX|FLUSH_FREE_TEMPX86)
|
||||
|
||||
// Note: All functions with _ee prefix are for EE only
|
||||
|
||||
// finds where the GPR is stored and moves lower 32 bits to EAX
|
||||
void _eeMoveGPRtoR(x86IntRegType to, int fromgpr);
|
||||
void _eeMoveGPRtoM(u32 to, int fromgpr);
|
||||
void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr);
|
||||
|
||||
void _psxMoveGPRtoR(x86IntRegType to, int fromgpr);
|
||||
void _psxMoveGPRtoM(u32 to, int fromgpr);
|
||||
void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr);
|
||||
|
||||
// uses MEM_MMXTAG/MEM_XMMTAG to differentiate between the regs
|
||||
void _recPushReg(int mmreg);
|
||||
|
||||
void _signExtendSFtoM(u32 mem);
|
||||
|
||||
// returns new index of reg, lower 32 bits already in mmx
|
||||
|
@ -264,10 +204,8 @@ int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy); // returns tr
|
|||
#define MEM_EECONSTTAG 0x0100 // argument is a GPR and comes from g_cpuConstRegs
|
||||
#define MEM_PSXCONSTTAG 0x0200
|
||||
#define MEM_MEMORYTAG 0x0400
|
||||
// mmreg is mmxreg
|
||||
#define MEM_MMXTAG 0x0800
|
||||
// mmreg is xmmreg
|
||||
#define MEM_XMMTAG 0x8000
|
||||
#define MEM_MMXTAG 0x0800 // mmreg is mmxreg
|
||||
#define MEM_XMMTAG 0x8000 // mmreg is xmmreg
|
||||
#define MEM_X86TAG 0x4000 // ignored most of the time
|
||||
#define MEM_GPRTAG 0x2000 // argument is a GPR reg
|
||||
#define MEM_CONSTTAG 0x1000 // argument is a const
|
||||
|
@ -319,13 +257,13 @@ struct EEINST
|
|||
};
|
||||
|
||||
extern EEINST* g_pCurInstInfo; // info for the cur instruction
|
||||
void _recClearInst(EEINST* pinst);
|
||||
extern void _recClearInst(EEINST* pinst);
|
||||
|
||||
// returns the number of insts + 1 until written (0 if not written)
|
||||
u32 _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg);
|
||||
extern u32 _recIsRegWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg);
|
||||
// returns the number of insts + 1 until used (0 if not used)
|
||||
u32 _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg);
|
||||
void _recFillRegister(EEINST& pinst, int type, int reg, int write);
|
||||
extern u32 _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg);
|
||||
extern void _recFillRegister(EEINST& pinst, int type, int reg, int write);
|
||||
|
||||
#define EEINST_ISLIVE64(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1))
|
||||
#define EEINST_ISLIVEXMM(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2))
|
||||
|
@ -345,21 +283,7 @@ void _recFillRegister(EEINST& pinst, int type, int reg, int write);
|
|||
#define EEINST_RESETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt &= ~(1<<(reg)); }
|
||||
#define EEINST_ISSIGNEXT(reg) (g_cpuPrevRegHasSignExt&(1<<(reg)))
|
||||
|
||||
// writeback inst (used for cop2)
|
||||
struct EEINSTWRITEBACK
|
||||
{
|
||||
int cycle;
|
||||
u32 viwrite; // mask of written viregs (REG_STATUS_FLAG and REG_MAC_FLAG are treated the same)
|
||||
EEINST* parent;
|
||||
};
|
||||
|
||||
void _recClearWritebacks();
|
||||
void _recAddWriteBack(int cycle, u32 viwrite, EEINST* parent);
|
||||
|
||||
// if cycle == -1, returns the next writeback (used for flushing)
|
||||
EEINSTWRITEBACK* _recCheckWriteBack(int cycle);
|
||||
|
||||
extern u32 g_recWriteback; // used for jumps
|
||||
extern u32 g_recWriteback; // used for jumps (VUrec mess!)
|
||||
extern u32 g_cpuRegHasLive1, g_cpuPrevRegHasLive1;
|
||||
extern u32 g_cpuRegHasSignExt, g_cpuPrevRegHasSignExt;
|
||||
|
||||
|
@ -379,35 +303,13 @@ int _allocCheckFPUtoXMM(EEINST* pinst, int fpureg, int mode);
|
|||
// allocates only if later insts use this register
|
||||
int _allocCheckGPRtoX86(EEINST* pinst, int gprreg, int mode);
|
||||
|
||||
// 0 - ee, 1 - iop
|
||||
void AddBaseBlockEx(BASEBLOCKEX*, int cpu);
|
||||
void RemoveBaseBlockEx(BASEBLOCKEX*, int cpu);
|
||||
BASEBLOCKEX* GetBaseBlockEx(u32 startpc, int cpu);
|
||||
void ResetBaseBlockEx(int cpu);
|
||||
|
||||
BASEBLOCKEX** GetAllBaseBlocks(int* pnum, int cpu);
|
||||
|
||||
#define MODE_READ 1
|
||||
#define MODE_WRITE 2
|
||||
#define MODE_READHALF 4 // read only low 64 bits
|
||||
#define MODE_VUXY 0x8 // vector only has xy valid (real zw are in mem), not the same as MODE_READHALF
|
||||
#define MODE_VUZ 0x10 // z only doesn't work for now
|
||||
#define MODE_VUXYZ (MODE_VUZ|MODE_VUXY) // vector only has xyz valid (real w is in memory)
|
||||
#define MODE_NOFLUSH 0x20 // can't flush reg to mem
|
||||
#define MODE_NOFRAME 0x40 // when allocating x86regs, don't use ebp reg
|
||||
#define MODE_8BITREG 0x80 // when allocating x86regs, use only eax, ecx, edx, and ebx
|
||||
|
||||
void SetMMXstate();
|
||||
|
||||
void _recMove128MtoM(u32 to, u32 from);
|
||||
|
||||
/////////////////////////////
|
||||
// MMX x86-32 only //
|
||||
/////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// MMX (64-bit) Register Allocation Tools
|
||||
|
||||
#define FPU_STATE 0
|
||||
#define MMX_STATE 1
|
||||
|
||||
void SetMMXstate();
|
||||
void SetFPUstate();
|
||||
|
||||
// max is 0x7f, when 0x80 is set, need to flush reg
|
||||
|
@ -453,33 +355,77 @@ int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode);
|
|||
void _recMove128RmOffsettoM(u32 to, u32 offset);
|
||||
void _recMove128MtoRmOffset(u32 offset, u32 from);
|
||||
|
||||
// op = 0, and
|
||||
// op = 1, or
|
||||
// op = 2, xor
|
||||
// op = 3, nor (the 32bit versoins only do OR)
|
||||
void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op);
|
||||
void LogicalOpMtoR(x86MMXRegType to, u32 from, int op);
|
||||
|
||||
// returns new index of reg, lower 32 bits already in mmx
|
||||
// shift is used when the data is in the top bits of the mmx reg to begin with
|
||||
// a negative shift is for sign extension
|
||||
int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift);
|
||||
extern int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift);
|
||||
|
||||
extern _mmxregs mmxregs[MMXREGS], s_saveMMXregs[MMXREGS];
|
||||
extern u16 x86FpuState, iCWstate;
|
||||
|
||||
void LogicalOp32RtoM(uptr to, x86IntRegType from, int op);
|
||||
void LogicalOp32MtoR(x86IntRegType to, uptr from, int op);
|
||||
void LogicalOp32ItoR(x86IntRegType to, u32 from, int op);
|
||||
void LogicalOp32ItoM(uptr to, u32 from, int op);
|
||||
extern void iDumpRegisters(u32 startpc, u32 temp);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// iFlushCall / _psxFlushCall Parameters
|
||||
|
||||
// Flushing vs. Freeing, as understood by Air (I could be wrong still....)
|
||||
|
||||
// "Freeing" registers means that the contents of the registers are flushed to memory.
|
||||
// This is good for any sort of C code function that plans to modify the actual
|
||||
// registers. When the Recs resume, they'll reload the registers with values saved
|
||||
// as needed. (similar to a "FreezeXMMRegs")
|
||||
|
||||
// "Flushing" means that in addition to the standard free (which is actually a flush)
|
||||
// the register allocations are additionally wiped. This should only be necessary if
|
||||
// the code being called is going to modify register allocations -- ie, be doing
|
||||
// some kind of recompiling of its own.
|
||||
|
||||
#define FLUSH_CACHED_REGS 1
|
||||
#define FLUSH_FLUSH_XMM 2
|
||||
#define FLUSH_FREE_XMM 4 // both flushes and frees
|
||||
#define FLUSH_FLUSH_MMX 8
|
||||
#define FLUSH_FREE_MMX 16 // both flushes and frees
|
||||
#define FLUSH_FLUSH_ALLX86 32 // flush x86
|
||||
#define FLUSH_FREE_TEMPX86 64 // flush and free temporary x86 regs
|
||||
#define FLUSH_FREE_ALLX86 128 // free all x86 regs
|
||||
#define FLUSH_FREE_VU0 0x100 // free all vu0 related regs
|
||||
|
||||
#define FLUSH_EVERYTHING 0xfff
|
||||
// no freeing, used when callee won't destroy mmx/xmm regs
|
||||
#define FLUSH_NODESTROY (FLUSH_CACHED_REGS|FLUSH_FLUSH_XMM|FLUSH_FLUSH_MMX|FLUSH_FLUSH_ALLX86)
|
||||
// used when regs aren't going to be changed be callee
|
||||
#define FLUSH_NOCONST (FLUSH_FREE_XMM|FLUSH_FREE_MMX|FLUSH_FREE_TEMPX86)
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Utility Functions -- that should probably be part of the Emitter.
|
||||
|
||||
// see MEM_X defines for argX format
|
||||
extern void _callPushArg(u32 arg, uptr argmem); /// X86ARG is ignored for 32bit recs
|
||||
extern void _callFunctionArg1(uptr fn, u32 arg1, uptr arg1mem);
|
||||
extern void _callFunctionArg2(uptr fn, u32 arg1, u32 arg2, uptr arg1mem, uptr arg2mem);
|
||||
extern void _callFunctionArg3(uptr fn, u32 arg1, u32 arg2, u32 arg3, uptr arg1mem, uptr arg2mem, uptr arg3mem);
|
||||
|
||||
// Moves 128 bits of data using EAX/EDX (used by iCOP2 only currently)
|
||||
extern void _recMove128MtoM(u32 to, u32 from);
|
||||
|
||||
// op = 0, and
|
||||
// op = 1, or
|
||||
// op = 2, xor
|
||||
// op = 3, nor (the 32bit versoins only do OR)
|
||||
extern void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op);
|
||||
extern void LogicalOpMtoR(x86MMXRegType to, u32 from, int op);
|
||||
|
||||
extern void LogicalOp32RtoM(uptr to, x86IntRegType from, int op);
|
||||
extern void LogicalOp32MtoR(x86IntRegType to, uptr from, int op);
|
||||
extern void LogicalOp32ItoR(x86IntRegType to, u32 from, int op);
|
||||
extern void LogicalOp32ItoM(uptr to, u32 from, int op);
|
||||
|
||||
#ifdef ARITHMETICIMM_RECOMPILE
|
||||
extern void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op);
|
||||
extern void LogicalOpMtoR(x86MMXRegType to, u32 from, int op);
|
||||
#endif
|
||||
|
||||
void iDumpRegisters(u32 startpc, u32 temp);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -328,6 +328,38 @@ void _psxDeleteReg(int reg, int flush)
|
|||
_deleteX86reg(X86TYPE_PSX, reg, flush ? 0 : 2);
|
||||
}
|
||||
|
||||
void _psxMoveGPRtoR(x86IntRegType to, int fromgpr)
|
||||
{
|
||||
if( PSX_IS_CONST1(fromgpr) )
|
||||
MOV32ItoR( to, g_psxConstRegs[fromgpr] );
|
||||
else {
|
||||
// check x86
|
||||
MOV32MtoR(to, (uptr)&psxRegs.GPR.r[ fromgpr ] );
|
||||
}
|
||||
}
|
||||
|
||||
void _psxMoveGPRtoM(u32 to, int fromgpr)
|
||||
{
|
||||
if( PSX_IS_CONST1(fromgpr) )
|
||||
MOV32ItoM( to, g_psxConstRegs[fromgpr] );
|
||||
else {
|
||||
// check x86
|
||||
MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[ fromgpr ] );
|
||||
MOV32RtoM(to, EAX );
|
||||
}
|
||||
}
|
||||
|
||||
void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr)
|
||||
{
|
||||
if( PSX_IS_CONST1(fromgpr) )
|
||||
MOV32ItoRmOffset( to, g_psxConstRegs[fromgpr], 0 );
|
||||
else {
|
||||
// check x86
|
||||
MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[ fromgpr ] );
|
||||
MOV32RtoRm(to, EAX );
|
||||
}
|
||||
}
|
||||
|
||||
void _psxFlushCall(int flushtype)
|
||||
{
|
||||
_freeX86regs();
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef _R3000A_SUPERREC_
|
||||
#define _R3000A_SUPERREC_
|
||||
|
||||
extern void __Log(const char *fmt, ...);
|
||||
#include "BaseblockEx.h"
|
||||
|
||||
// Cycle penalties for particuarly slow instructions.
|
||||
static const int psxInstCycles_Mult = 8;
|
||||
|
@ -50,6 +50,11 @@ void _psxDeleteReg(int reg, int flush);
|
|||
void _psxFlushCall(int flushtype);
|
||||
|
||||
void _psxOnWriteReg(int reg);
|
||||
|
||||
void _psxMoveGPRtoR(x86IntRegType to, int fromgpr);
|
||||
void _psxMoveGPRtoM(u32 to, int fromgpr);
|
||||
void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr);
|
||||
|
||||
void PSX_CHECK_SAVE_REG(int reg);
|
||||
|
||||
extern u32 psxpc; // recompiler pc
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "R5900.h"
|
||||
#include "VU.h"
|
||||
#include "iCore.h"
|
||||
#include "BaseblockEx.h" // needed for recClear and stuff
|
||||
|
||||
// Yay! These work now! (air)
|
||||
#define ARITHMETICIMM_RECOMPILE
|
||||
|
@ -112,6 +113,11 @@ extern void (*recBSC_co[64])();
|
|||
|
||||
u32* _eeGetConstReg(int reg); // gets a memory pointer to the constant reg
|
||||
|
||||
// finds where the GPR is stored and moves lower 32 bits to EAX
|
||||
void _eeMoveGPRtoR(x86IntRegType to, int fromgpr);
|
||||
void _eeMoveGPRtoM(u32 to, int fromgpr);
|
||||
void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr);
|
||||
|
||||
void _eeFlushAllUnused();
|
||||
void _eeOnWriteReg(int reg, int signext);
|
||||
|
||||
|
|
|
@ -25,10 +25,12 @@
|
|||
#include "iCore.h"
|
||||
#include "R3000A.h"
|
||||
|
||||
#include "iR5900.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
using namespace R5900;
|
||||
using namespace ::R5900;
|
||||
|
||||
namespace Dynarec
|
||||
{
|
||||
|
@ -66,7 +68,8 @@ u32 _x86GetAddr(int type, int reg)
|
|||
return (u32)&g_recWriteback;
|
||||
case X86TYPE_VUJUMP:
|
||||
return (u32)&g_recWriteback;
|
||||
default: assert(0);
|
||||
|
||||
jNO_DEFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -279,7 +282,7 @@ int _allocX86reg(int x86reg, int type, int reg, int mode)
|
|||
_deleteMMXreg(MMX_GPR+reg, 1);
|
||||
_deleteGPRtoXMMreg(reg, 1);
|
||||
|
||||
_eeMoveGPRtoR(x86reg, reg);
|
||||
R5900::_eeMoveGPRtoR(x86reg, reg);
|
||||
|
||||
_deleteMMXreg(MMX_GPR+reg, 0);
|
||||
_deleteGPRtoXMMreg(reg, 0);
|
||||
|
@ -819,7 +822,7 @@ __forceinline void _callPushArg(u32 arg, uptr argmem)
|
|||
else if( IS_CONSTREG(arg) ) PUSH32I(argmem);
|
||||
else if( IS_GPRREG(arg) ) {
|
||||
SUB32ItoR(ESP, 4);
|
||||
_eeMoveGPRtoRm(ESP, arg&0xff);
|
||||
R5900::_eeMoveGPRtoRm(ESP, arg&0xff);
|
||||
}
|
||||
else if( IS_XMMREG(arg) ) {
|
||||
SUB32ItoR(ESP, 4);
|
||||
|
@ -867,69 +870,6 @@ __forceinline void _callFunctionArg3(uptr fn, u32 arg1, u32 arg2, u32 arg3, uptr
|
|||
ADD32ItoR(ESP, 12);
|
||||
}
|
||||
|
||||
// EE
|
||||
void _eeMoveGPRtoR(x86IntRegType to, int fromgpr)
|
||||
{
|
||||
if( GPR_IS_CONST1(fromgpr) )
|
||||
MOV32ItoR( to, g_cpuConstRegs[fromgpr].UL[0] );
|
||||
else {
|
||||
int mmreg;
|
||||
|
||||
if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 && (xmmregs[mmreg].mode&MODE_WRITE)) {
|
||||
SSE2_MOVD_XMM_to_R(to, mmreg);
|
||||
}
|
||||
else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE) ) {
|
||||
MOVD32MMXtoR(to, mmreg);
|
||||
SetMMXstate();
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(to, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _eeMoveGPRtoM(u32 to, int fromgpr)
|
||||
{
|
||||
if( GPR_IS_CONST1(fromgpr) )
|
||||
MOV32ItoM( to, g_cpuConstRegs[fromgpr].UL[0] );
|
||||
else {
|
||||
int mmreg;
|
||||
|
||||
if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) {
|
||||
SSEX_MOVD_XMM_to_M32(to, mmreg);
|
||||
}
|
||||
else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) {
|
||||
MOVDMMXtoM(to, mmreg);
|
||||
SetMMXstate();
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] );
|
||||
MOV32RtoM(to, EAX );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr)
|
||||
{
|
||||
if( GPR_IS_CONST1(fromgpr) )
|
||||
MOV32ItoRmOffset( to, g_cpuConstRegs[fromgpr].UL[0], 0 );
|
||||
else {
|
||||
int mmreg;
|
||||
|
||||
if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) {
|
||||
SSEX_MOVD_XMM_to_Rm(to, mmreg);
|
||||
}
|
||||
else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) {
|
||||
MOVD32MMXtoRm(to, mmreg);
|
||||
SetMMXstate();
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] );
|
||||
MOV32RtoRm(to, EAX );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _recPushReg(int mmreg)
|
||||
{
|
||||
if( IS_XMMREG(mmreg) ) {
|
||||
|
@ -1070,6 +1010,8 @@ int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode)
|
|||
return _checkMMXreg(MMX_GPR+reg, mode);
|
||||
}
|
||||
|
||||
// fixme - yay stupid? This sucks, and is used form iCOp2.cpp only.
|
||||
// Surely there is a better way!
|
||||
void _recMove128MtoM(u32 to, u32 from)
|
||||
{
|
||||
MOV32MtoR(EAX, from);
|
||||
|
@ -1082,6 +1024,7 @@ void _recMove128MtoM(u32 to, u32 from)
|
|||
MOV32RtoM(to+12, EDX);
|
||||
}
|
||||
|
||||
// fixme - see above function!
|
||||
void _recMove128RmOffsettoM(u32 to, u32 offset)
|
||||
{
|
||||
MOV32RmtoROffset(EAX, ECX, offset);
|
||||
|
@ -1094,6 +1037,7 @@ void _recMove128RmOffsettoM(u32 to, u32 offset)
|
|||
MOV32RtoM(to+12, EDX);
|
||||
}
|
||||
|
||||
// fixme - see above function again!
|
||||
void _recMove128MtoRmOffset(u32 offset, u32 from)
|
||||
{
|
||||
MOV32MtoR(EAX, from);
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
#include "VUmicro.h"
|
||||
|
||||
#include "iVUzerorec.h"
|
||||
|
||||
#include "vtlb.h"
|
||||
|
||||
#include "SamplProf.h"
|
||||
|
||||
// used to disable register freezing during cpuBranchTests (registers
|
||||
|
@ -338,6 +338,68 @@ u32* _eeGetConstReg(int reg)
|
|||
return &cpuRegs.GPR.r[ reg ].UL[0];
|
||||
}
|
||||
|
||||
void _eeMoveGPRtoR(x86IntRegType to, int fromgpr)
|
||||
{
|
||||
if( GPR_IS_CONST1(fromgpr) )
|
||||
MOV32ItoR( to, g_cpuConstRegs[fromgpr].UL[0] );
|
||||
else {
|
||||
int mmreg;
|
||||
|
||||
if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 && (xmmregs[mmreg].mode&MODE_WRITE)) {
|
||||
SSE2_MOVD_XMM_to_R(to, mmreg);
|
||||
}
|
||||
else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 && (mmxregs[mmreg].mode&MODE_WRITE) ) {
|
||||
MOVD32MMXtoR(to, mmreg);
|
||||
SetMMXstate();
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(to, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _eeMoveGPRtoM(u32 to, int fromgpr)
|
||||
{
|
||||
if( GPR_IS_CONST1(fromgpr) )
|
||||
MOV32ItoM( to, g_cpuConstRegs[fromgpr].UL[0] );
|
||||
else {
|
||||
int mmreg;
|
||||
|
||||
if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) {
|
||||
SSEX_MOVD_XMM_to_M32(to, mmreg);
|
||||
}
|
||||
else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) {
|
||||
MOVDMMXtoM(to, mmreg);
|
||||
SetMMXstate();
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] );
|
||||
MOV32RtoM(to, EAX );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _eeMoveGPRtoRm(x86IntRegType to, int fromgpr)
|
||||
{
|
||||
if( GPR_IS_CONST1(fromgpr) )
|
||||
MOV32ItoRmOffset( to, g_cpuConstRegs[fromgpr].UL[0], 0 );
|
||||
else {
|
||||
int mmreg;
|
||||
|
||||
if( (mmreg = _checkXMMreg(XMMTYPE_GPRREG, fromgpr, MODE_READ)) >= 0 ) {
|
||||
SSEX_MOVD_XMM_to_Rm(to, mmreg);
|
||||
}
|
||||
else if( (mmreg = _checkMMXreg(MMX_GPR+fromgpr, MODE_READ)) >= 0 ) {
|
||||
MOVD32MMXtoRm(to, mmreg);
|
||||
SetMMXstate();
|
||||
}
|
||||
else {
|
||||
MOV32MtoR(EAX, (int)&cpuRegs.GPR.r[ fromgpr ].UL[ 0 ] );
|
||||
MOV32RtoRm(to, EAX );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int _flushXMMunused()
|
||||
{
|
||||
int i;
|
||||
|
@ -1618,7 +1680,6 @@ void recRecompile( const u32 startpc )
|
|||
g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
|
||||
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff;
|
||||
g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0;
|
||||
_recClearWritebacks();
|
||||
assert( g_cpuConstRegs[0].UD[0] == 0 );
|
||||
|
||||
_initX86regs();
|
||||
|
|
Loading…
Reference in New Issue