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:
Jake.Stine 2009-01-21 17:11:26 +00:00 committed by Gregory Hainaut
parent 46f5bb51e9
commit cb70542e4c
10 changed files with 260 additions and 424 deletions

View File

@ -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"

View File

@ -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);
}

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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();