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 "VU.h"
|
||||||
#include "iCore.h"
|
#include "iCore.h"
|
||||||
#include "iVUzerorec.h"
|
#include "iVUzerorec.h"
|
||||||
|
#include "BaseblockEx.h" // for debuild block dumping (which may or may not work anymore?)
|
||||||
|
|
||||||
#include "GS.h"
|
#include "GS.h"
|
||||||
#include "COP0.h"
|
#include "COP0.h"
|
||||||
|
|
|
@ -119,7 +119,6 @@ int AddPatch(int Mode, int Place, int Address, int Size, u64 data);
|
||||||
|
|
||||||
namespace Dynarec {
|
namespace Dynarec {
|
||||||
extern void SetFastMemory(int); // iR5900LoadStore.c
|
extern void SetFastMemory(int); // iR5900LoadStore.c
|
||||||
extern void SetVUNanMemory(int); // iVUmicro.c
|
|
||||||
extern void SetVUNanMode(int mode);
|
extern void SetVUNanMode(int mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2176,6 +2176,14 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="Ps2"
|
Name="Ps2"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\x86\BaseblockEx.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\x86\BaseblockEx.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<Filter
|
<Filter
|
||||||
Name="EE"
|
Name="EE"
|
||||||
>
|
>
|
||||||
|
@ -2421,6 +2429,14 @@
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\x86\ix86-32\iR5900-32.cpp"
|
RelativePath="..\..\x86\ix86-32\iR5900-32.cpp"
|
||||||
>
|
>
|
||||||
|
<FileConfiguration
|
||||||
|
Name="Devel vtlb|Win32"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
AssemblerOutput="4"
|
||||||
|
/>
|
||||||
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\x86\ix86-32\iR5900Arit.cpp"
|
RelativePath="..\..\x86\ix86-32\iR5900Arit.cpp"
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
#include "PS2Etypes.h"
|
|
||||||
|
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
#include "R5900.h"
|
#include "R5900.h"
|
||||||
#include "Vif.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};
|
PCSX2_ALIGNED16(u32 s_zeros[4]) = {0};
|
||||||
int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy)
|
int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy)
|
||||||
{
|
{
|
||||||
|
@ -1177,145 +1142,6 @@ void SetMMXstate() {
|
||||||
x86FpuState = MMX_STATE;
|
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 "R3000A.h"
|
||||||
//#include "PsxCounters.h"
|
//#include "PsxCounters.h"
|
||||||
|
|
|
@ -22,41 +22,70 @@
|
||||||
#include "ix86/ix86.h"
|
#include "ix86/ix86.h"
|
||||||
#include "iVUmicro.h"
|
#include "iVUmicro.h"
|
||||||
|
|
||||||
// Namespace Note : Dyanmic recompiler tools used by EE, IOP, and PS2 hardware.
|
// Namespace Note : iCore32 contains all of the Register Allocation logic, in addition to a handful
|
||||||
// Underneath this namespace thenare Dynarec::R5900, Dynarec::R3000a, etc. for each
|
// of utility functions for emitting frequent code.
|
||||||
// of the items specific to those CPUs (those are defined in other headers).
|
|
||||||
|
|
||||||
namespace Dynarec
|
namespace Dynarec
|
||||||
{
|
{
|
||||||
// used to keep block information
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
#define BLOCKTYPE_STARTPC 4 // startpc offset
|
// Shared Register allocation flags (apply to X86, XMM, MMX, etc).
|
||||||
#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot
|
|
||||||
|
|
||||||
struct BASEBLOCK
|
#define MODE_READ 1
|
||||||
{
|
#define MODE_WRITE 2
|
||||||
u32 pFnptr : 28;
|
#define MODE_READHALF 4 // read only low 64 bits
|
||||||
u32 uType : 4;
|
#define MODE_VUXY 0x8 // vector only has xy valid (real zw are in mem), not the same as MODE_READHALF
|
||||||
u32 startpc;
|
#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)
|
// currently only used in FPU
|
||||||
struct BASEBLOCKEX
|
#define PROCESS_EE_S 0x04 // S is valid, otherwise take from mem
|
||||||
{
|
#define PROCESS_EE_T 0x08 // T is valid, otherwise take from mem
|
||||||
u16 size; // size in dwords
|
|
||||||
u16 dummy;
|
|
||||||
u32 startpc; // for debugging?
|
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
// not used in VU recs
|
||||||
u32 visited; // number of times called
|
#define PROCESS_EE_MODEWRITES 0x10 // if s is a reg, set if not in cpuRegs
|
||||||
LARGE_INTEGER ltime; // regs it assumes to have set already
|
#define PROCESS_EE_MODEWRITET 0x20 // if t is a reg, set if not in cpuRegs
|
||||||
#endif
|
#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 EEREC_S (((info)>>8)&0xf)
|
||||||
#define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (sizeof(BASEBLOCK)/4)*((x) & 0xffff)))
|
#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_TEMP 0
|
||||||
#define X86TYPE_GPR 1
|
#define X86TYPE_GPR 1
|
||||||
|
@ -106,56 +135,8 @@ void _flushCachedRegs();
|
||||||
void _flushConstRegs();
|
void _flushConstRegs();
|
||||||
void _flushConstReg(int reg);
|
void _flushConstReg(int reg);
|
||||||
|
|
||||||
// see MEM_X defines for argX format
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
extern void _callPushArg(u32 arg, uptr argmem); /// X86ARG is ignored for 32bit recs
|
// XMM (128-bit) Register Allocation Tools
|
||||||
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
|
|
||||||
|
|
||||||
#define XMM_CONV_VU(VU) (VU==&VU1)
|
#define XMM_CONV_VU(VU) (VU==&VU1)
|
||||||
|
|
||||||
|
@ -207,49 +188,8 @@ u8 _hasFreeXMMreg();
|
||||||
void _freeXMMregs();
|
void _freeXMMregs();
|
||||||
int _getNumXMMwrite();
|
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
|
// uses MEM_MMXTAG/MEM_XMMTAG to differentiate between the regs
|
||||||
void _recPushReg(int mmreg);
|
void _recPushReg(int mmreg);
|
||||||
|
|
||||||
void _signExtendSFtoM(u32 mem);
|
void _signExtendSFtoM(u32 mem);
|
||||||
|
|
||||||
// returns new index of reg, lower 32 bits already in mmx
|
// 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_EECONSTTAG 0x0100 // argument is a GPR and comes from g_cpuConstRegs
|
||||||
#define MEM_PSXCONSTTAG 0x0200
|
#define MEM_PSXCONSTTAG 0x0200
|
||||||
#define MEM_MEMORYTAG 0x0400
|
#define MEM_MEMORYTAG 0x0400
|
||||||
// mmreg is mmxreg
|
#define MEM_MMXTAG 0x0800 // mmreg is mmxreg
|
||||||
#define MEM_MMXTAG 0x0800
|
#define MEM_XMMTAG 0x8000 // mmreg is xmmreg
|
||||||
// mmreg is xmmreg
|
|
||||||
#define MEM_XMMTAG 0x8000
|
|
||||||
#define MEM_X86TAG 0x4000 // ignored most of the time
|
#define MEM_X86TAG 0x4000 // ignored most of the time
|
||||||
#define MEM_GPRTAG 0x2000 // argument is a GPR reg
|
#define MEM_GPRTAG 0x2000 // argument is a GPR reg
|
||||||
#define MEM_CONSTTAG 0x1000 // argument is a const
|
#define MEM_CONSTTAG 0x1000 // argument is a const
|
||||||
|
@ -319,13 +257,13 @@ struct EEINST
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EEINST* g_pCurInstInfo; // info for the cur instruction
|
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)
|
// 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)
|
// returns the number of insts + 1 until used (0 if not used)
|
||||||
u32 _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg);
|
extern u32 _recIsRegUsed(EEINST* pinst, int size, u8 xmmtype, u8 reg);
|
||||||
void _recFillRegister(EEINST& pinst, int type, int reg, int write);
|
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_ISLIVE64(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1))
|
||||||
#define EEINST_ISLIVEXMM(reg) (g_pCurInstInfo->regs[reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2))
|
#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_RESETSIGNEXT(reg) { if( (reg) < 32 ) g_cpuRegHasSignExt &= ~(1<<(reg)); }
|
||||||
#define EEINST_ISSIGNEXT(reg) (g_cpuPrevRegHasSignExt&(1<<(reg)))
|
#define EEINST_ISSIGNEXT(reg) (g_cpuPrevRegHasSignExt&(1<<(reg)))
|
||||||
|
|
||||||
// writeback inst (used for cop2)
|
extern u32 g_recWriteback; // used for jumps (VUrec mess!)
|
||||||
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_cpuRegHasLive1, g_cpuPrevRegHasLive1;
|
extern u32 g_cpuRegHasLive1, g_cpuPrevRegHasLive1;
|
||||||
extern u32 g_cpuRegHasSignExt, g_cpuPrevRegHasSignExt;
|
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
|
// allocates only if later insts use this register
|
||||||
int _allocCheckGPRtoX86(EEINST* pinst, int gprreg, int mode);
|
int _allocCheckGPRtoX86(EEINST* pinst, int gprreg, int mode);
|
||||||
|
|
||||||
// 0 - ee, 1 - iop
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void AddBaseBlockEx(BASEBLOCKEX*, int cpu);
|
// MMX (64-bit) Register Allocation Tools
|
||||||
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 //
|
|
||||||
/////////////////////////////
|
|
||||||
|
|
||||||
#define FPU_STATE 0
|
#define FPU_STATE 0
|
||||||
#define MMX_STATE 1
|
#define MMX_STATE 1
|
||||||
|
|
||||||
|
void SetMMXstate();
|
||||||
void SetFPUstate();
|
void SetFPUstate();
|
||||||
|
|
||||||
// max is 0x7f, when 0x80 is set, need to flush reg
|
// 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 _recMove128RmOffsettoM(u32 to, u32 offset);
|
||||||
void _recMove128MtoRmOffset(u32 offset, u32 from);
|
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
|
// 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
|
// 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
|
// 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 _mmxregs mmxregs[MMXREGS], s_saveMMXregs[MMXREGS];
|
||||||
extern u16 x86FpuState, iCWstate;
|
extern u16 x86FpuState, iCWstate;
|
||||||
|
|
||||||
void LogicalOp32RtoM(uptr to, x86IntRegType from, int op);
|
extern void iDumpRegisters(u32 startpc, u32 temp);
|
||||||
void LogicalOp32MtoR(x86IntRegType to, uptr from, int op);
|
|
||||||
void LogicalOp32ItoR(x86IntRegType to, u32 from, int op);
|
//////////////////////////////////////////////////////////////////////////
|
||||||
void LogicalOp32ItoM(uptr to, u32 from, int op);
|
// 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
|
#ifdef ARITHMETICIMM_RECOMPILE
|
||||||
extern void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op);
|
extern void LogicalOpRtoR(x86MMXRegType to, x86MMXRegType from, int op);
|
||||||
extern void LogicalOpMtoR(x86MMXRegType to, u32 from, int op);
|
extern void LogicalOpMtoR(x86MMXRegType to, u32 from, int op);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void iDumpRegisters(u32 startpc, u32 temp);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -328,6 +328,38 @@ void _psxDeleteReg(int reg, int flush)
|
||||||
_deleteX86reg(X86TYPE_PSX, reg, flush ? 0 : 2);
|
_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)
|
void _psxFlushCall(int flushtype)
|
||||||
{
|
{
|
||||||
_freeX86regs();
|
_freeX86regs();
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef _R3000A_SUPERREC_
|
#ifndef _R3000A_SUPERREC_
|
||||||
#define _R3000A_SUPERREC_
|
#define _R3000A_SUPERREC_
|
||||||
|
|
||||||
extern void __Log(const char *fmt, ...);
|
#include "BaseblockEx.h"
|
||||||
|
|
||||||
// Cycle penalties for particuarly slow instructions.
|
// Cycle penalties for particuarly slow instructions.
|
||||||
static const int psxInstCycles_Mult = 8;
|
static const int psxInstCycles_Mult = 8;
|
||||||
|
@ -50,6 +50,11 @@ void _psxDeleteReg(int reg, int flush);
|
||||||
void _psxFlushCall(int flushtype);
|
void _psxFlushCall(int flushtype);
|
||||||
|
|
||||||
void _psxOnWriteReg(int reg);
|
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);
|
void PSX_CHECK_SAVE_REG(int reg);
|
||||||
|
|
||||||
extern u32 psxpc; // recompiler pc
|
extern u32 psxpc; // recompiler pc
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "R5900.h"
|
#include "R5900.h"
|
||||||
#include "VU.h"
|
#include "VU.h"
|
||||||
#include "iCore.h"
|
#include "iCore.h"
|
||||||
|
#include "BaseblockEx.h" // needed for recClear and stuff
|
||||||
|
|
||||||
// Yay! These work now! (air)
|
// Yay! These work now! (air)
|
||||||
#define ARITHMETICIMM_RECOMPILE
|
#define ARITHMETICIMM_RECOMPILE
|
||||||
|
@ -112,6 +113,11 @@ extern void (*recBSC_co[64])();
|
||||||
|
|
||||||
u32* _eeGetConstReg(int reg); // gets a memory pointer to the constant reg
|
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 _eeFlushAllUnused();
|
||||||
void _eeOnWriteReg(int reg, int signext);
|
void _eeOnWriteReg(int reg, int signext);
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,12 @@
|
||||||
#include "iCore.h"
|
#include "iCore.h"
|
||||||
#include "R3000A.h"
|
#include "R3000A.h"
|
||||||
|
|
||||||
|
#include "iR5900.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace R5900;
|
using namespace ::R5900;
|
||||||
|
|
||||||
namespace Dynarec
|
namespace Dynarec
|
||||||
{
|
{
|
||||||
|
@ -66,7 +68,8 @@ u32 _x86GetAddr(int type, int reg)
|
||||||
return (u32)&g_recWriteback;
|
return (u32)&g_recWriteback;
|
||||||
case X86TYPE_VUJUMP:
|
case X86TYPE_VUJUMP:
|
||||||
return (u32)&g_recWriteback;
|
return (u32)&g_recWriteback;
|
||||||
default: assert(0);
|
|
||||||
|
jNO_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -279,7 +282,7 @@ int _allocX86reg(int x86reg, int type, int reg, int mode)
|
||||||
_deleteMMXreg(MMX_GPR+reg, 1);
|
_deleteMMXreg(MMX_GPR+reg, 1);
|
||||||
_deleteGPRtoXMMreg(reg, 1);
|
_deleteGPRtoXMMreg(reg, 1);
|
||||||
|
|
||||||
_eeMoveGPRtoR(x86reg, reg);
|
R5900::_eeMoveGPRtoR(x86reg, reg);
|
||||||
|
|
||||||
_deleteMMXreg(MMX_GPR+reg, 0);
|
_deleteMMXreg(MMX_GPR+reg, 0);
|
||||||
_deleteGPRtoXMMreg(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_CONSTREG(arg) ) PUSH32I(argmem);
|
||||||
else if( IS_GPRREG(arg) ) {
|
else if( IS_GPRREG(arg) ) {
|
||||||
SUB32ItoR(ESP, 4);
|
SUB32ItoR(ESP, 4);
|
||||||
_eeMoveGPRtoRm(ESP, arg&0xff);
|
R5900::_eeMoveGPRtoRm(ESP, arg&0xff);
|
||||||
}
|
}
|
||||||
else if( IS_XMMREG(arg) ) {
|
else if( IS_XMMREG(arg) ) {
|
||||||
SUB32ItoR(ESP, 4);
|
SUB32ItoR(ESP, 4);
|
||||||
|
@ -867,69 +870,6 @@ __forceinline void _callFunctionArg3(uptr fn, u32 arg1, u32 arg2, u32 arg3, uptr
|
||||||
ADD32ItoR(ESP, 12);
|
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)
|
void _recPushReg(int mmreg)
|
||||||
{
|
{
|
||||||
if( IS_XMMREG(mmreg) ) {
|
if( IS_XMMREG(mmreg) ) {
|
||||||
|
@ -1070,6 +1010,8 @@ int _allocCheckGPRtoMMX(EEINST* pinst, int reg, int mode)
|
||||||
return _checkMMXreg(MMX_GPR+reg, 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)
|
void _recMove128MtoM(u32 to, u32 from)
|
||||||
{
|
{
|
||||||
MOV32MtoR(EAX, from);
|
MOV32MtoR(EAX, from);
|
||||||
|
@ -1082,6 +1024,7 @@ void _recMove128MtoM(u32 to, u32 from)
|
||||||
MOV32RtoM(to+12, EDX);
|
MOV32RtoM(to+12, EDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fixme - see above function!
|
||||||
void _recMove128RmOffsettoM(u32 to, u32 offset)
|
void _recMove128RmOffsettoM(u32 to, u32 offset)
|
||||||
{
|
{
|
||||||
MOV32RmtoROffset(EAX, ECX, offset);
|
MOV32RmtoROffset(EAX, ECX, offset);
|
||||||
|
@ -1094,6 +1037,7 @@ void _recMove128RmOffsettoM(u32 to, u32 offset)
|
||||||
MOV32RtoM(to+12, EDX);
|
MOV32RtoM(to+12, EDX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fixme - see above function again!
|
||||||
void _recMove128MtoRmOffset(u32 offset, u32 from)
|
void _recMove128MtoRmOffset(u32 offset, u32 from)
|
||||||
{
|
{
|
||||||
MOV32MtoR(EAX, from);
|
MOV32MtoR(EAX, from);
|
||||||
|
|
|
@ -39,8 +39,8 @@
|
||||||
#include "VUmicro.h"
|
#include "VUmicro.h"
|
||||||
|
|
||||||
#include "iVUzerorec.h"
|
#include "iVUzerorec.h"
|
||||||
|
|
||||||
#include "vtlb.h"
|
#include "vtlb.h"
|
||||||
|
|
||||||
#include "SamplProf.h"
|
#include "SamplProf.h"
|
||||||
|
|
||||||
// used to disable register freezing during cpuBranchTests (registers
|
// used to disable register freezing during cpuBranchTests (registers
|
||||||
|
@ -338,6 +338,68 @@ u32* _eeGetConstReg(int reg)
|
||||||
return &cpuRegs.GPR.r[ reg ].UL[0];
|
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 _flushXMMunused()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1618,7 +1680,6 @@ void recRecompile( const u32 startpc )
|
||||||
g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
|
g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
|
||||||
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff;
|
g_cpuPrevRegHasLive1 = g_cpuRegHasLive1 = 0xffffffff;
|
||||||
g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0;
|
g_cpuPrevRegHasSignExt = g_cpuRegHasSignExt = 0;
|
||||||
_recClearWritebacks();
|
|
||||||
assert( g_cpuConstRegs[0].UD[0] == 0 );
|
assert( g_cpuConstRegs[0].UD[0] == 0 );
|
||||||
|
|
||||||
_initX86regs();
|
_initX86regs();
|
||||||
|
|
Loading…
Reference in New Issue