mirror of https://github.com/PCSX2/pcsx2.git
aligned_stack: Finished conversion of all CALLFunc and _callFunctionArg1 functions to aligned-stack safe __fastcall invocations; only IOP's psxExecute and dispatchers remain to be done. (rev is fully functional in this state tho, on win32 at least)
git-svn-id: http://pcsx2.googlecode.com/svn/branches/aligned_stack@2045 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
e3a5229076
commit
3e1c1f939c
|
@ -31,11 +31,6 @@ typedef int x86IntRegType;
|
|||
#define EBP 5
|
||||
#define ESP 4
|
||||
|
||||
#define X86ARG1 EAX
|
||||
#define X86ARG2 ECX
|
||||
#define X86ARG3 EDX
|
||||
#define X86ARG4 EBX
|
||||
|
||||
#define MM0 0
|
||||
#define MM1 1
|
||||
#define MM2 2
|
||||
|
|
|
@ -38,7 +38,7 @@ __releaseinline void UpdateCP0Status() {
|
|||
cpuTestHwInts();
|
||||
}
|
||||
|
||||
void WriteCP0Status(u32 value) {
|
||||
void __fastcall WriteCP0Status(u32 value) {
|
||||
cpuRegs.CP0.n.Status.val = value;
|
||||
UpdateCP0Status();
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ __forceinline void COP0_UpdatePCCR()
|
|||
//if( cpuRegs.CP0.n.Status.b.ERL || !cpuRegs.PERF.n.pccr.b.CTE ) return;
|
||||
|
||||
// TODO : Implement memory mode checks here (kernel/super/user)
|
||||
// For now we just assume user mode.
|
||||
// For now we just assume kernel mode.
|
||||
|
||||
if( cpuRegs.PERF.n.pccr.val & 0xf )
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#ifndef __COP0_H__
|
||||
#define __COP0_H__
|
||||
|
||||
extern void WriteCP0Status(u32 value);
|
||||
extern void __fastcall WriteCP0Status(u32 value);
|
||||
extern void UpdateCP0Status();
|
||||
extern void WriteTLB(int i);
|
||||
extern void UnmapTLB(int i);
|
||||
|
|
|
@ -115,7 +115,7 @@ void psxMemShutdown()
|
|||
psxMemRLUT = NULL;
|
||||
}
|
||||
|
||||
u8 iopMemRead8(u32 mem)
|
||||
u8 __fastcall iopMemRead8(u32 mem)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
@ -159,7 +159,7 @@ u8 iopMemRead8(u32 mem)
|
|||
}
|
||||
}
|
||||
|
||||
u16 iopMemRead16(u32 mem)
|
||||
u16 __fastcall iopMemRead16(u32 mem)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
@ -225,7 +225,7 @@ u16 iopMemRead16(u32 mem)
|
|||
}
|
||||
}
|
||||
|
||||
u32 iopMemRead32(u32 mem)
|
||||
u32 __fastcall iopMemRead32(u32 mem)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
@ -294,7 +294,7 @@ u32 iopMemRead32(u32 mem)
|
|||
}
|
||||
}
|
||||
|
||||
void iopMemWrite8(u32 mem, u8 value)
|
||||
void __fastcall iopMemWrite8(u32 mem, u8 value)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
@ -356,7 +356,7 @@ void iopMemWrite8(u32 mem, u8 value)
|
|||
}
|
||||
}
|
||||
|
||||
void iopMemWrite16(u32 mem, u16 value)
|
||||
void __fastcall iopMemWrite16(u32 mem, u16 value)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
@ -440,7 +440,7 @@ void iopMemWrite16(u32 mem, u16 value)
|
|||
}
|
||||
}
|
||||
|
||||
void iopMemWrite32(u32 mem, u32 value)
|
||||
void __fastcall iopMemWrite32(u32 mem, u32 value)
|
||||
{
|
||||
mem &= 0x1fffffff;
|
||||
u32 t = mem >> 16;
|
||||
|
|
|
@ -75,24 +75,24 @@ static __forceinline u8* iopPhysMem( u32 addr )
|
|||
#define psxHu16(mem) (*(u16*)&psxH[(mem) & 0xffff])
|
||||
#define psxHu32(mem) (*(u32*)&psxH[(mem) & 0xffff])
|
||||
|
||||
void psxMemAlloc();
|
||||
void psxMemReset();
|
||||
void psxMemShutdown();
|
||||
extern void psxMemAlloc();
|
||||
extern void psxMemReset();
|
||||
extern void psxMemShutdown();
|
||||
|
||||
u8 iopMemRead8 (u32 mem);
|
||||
u16 iopMemRead16(u32 mem);
|
||||
u32 iopMemRead32(u32 mem);
|
||||
void iopMemWrite8 (u32 mem, u8 value);
|
||||
void iopMemWrite16(u32 mem, u16 value);
|
||||
void iopMemWrite32(u32 mem, u32 value);
|
||||
extern u8 __fastcall iopMemRead8 (u32 mem);
|
||||
extern u16 __fastcall iopMemRead16(u32 mem);
|
||||
extern u32 __fastcall iopMemRead32(u32 mem);
|
||||
extern void __fastcall iopMemWrite8 (u32 mem, u8 value);
|
||||
extern void __fastcall iopMemWrite16(u32 mem, u16 value);
|
||||
extern void __fastcall iopMemWrite32(u32 mem, u32 value);
|
||||
|
||||
// x86reg and mmreg are always x86 regs
|
||||
void psxRecMemRead8();
|
||||
void psxRecMemRead16();
|
||||
void psxRecMemRead32();
|
||||
void psxRecMemWrite8();
|
||||
void psxRecMemWrite16();
|
||||
void psxRecMemWrite32();
|
||||
extern void psxRecMemRead8();
|
||||
extern void psxRecMemRead16();
|
||||
extern void psxRecMemRead32();
|
||||
extern void psxRecMemWrite8();
|
||||
extern void psxRecMemWrite16();
|
||||
extern void psxRecMemWrite32();
|
||||
|
||||
namespace IopMemory
|
||||
{
|
||||
|
|
|
@ -70,7 +70,8 @@ void psxShutdown() {
|
|||
//psxCpu->Shutdown();
|
||||
}
|
||||
|
||||
void psxException(u32 code, u32 bd) {
|
||||
void __fastcall psxException(u32 code, u32 bd)
|
||||
{
|
||||
// PSXCPU_LOG("psxException %x: %x, %x", code, psxHu32(0x1070), psxHu32(0x1074));
|
||||
//Console.WriteLn("!! psxException %x: %x, %x", code, psxHu32(0x1070), psxHu32(0x1074));
|
||||
// Set the Cause
|
||||
|
|
|
@ -194,11 +194,11 @@ extern R3000Acpu *psxCpu;
|
|||
extern R3000Acpu psxInt;
|
||||
extern R3000Acpu psxRec;
|
||||
|
||||
void psxReset();
|
||||
void psxShutdown();
|
||||
void psxException(u32 code, u32 step);
|
||||
extern void psxReset();
|
||||
extern void psxShutdown();
|
||||
extern void __fastcall psxException(u32 code, u32 step);
|
||||
extern void psxBranchTest();
|
||||
void psxMemReset();
|
||||
extern void psxMemReset();
|
||||
|
||||
// Subsets
|
||||
extern void (*psxBSC[64])();
|
||||
|
|
|
@ -50,7 +50,7 @@ void VU0MI_XGKICK() {
|
|||
void VU0MI_XTOP() {
|
||||
}
|
||||
|
||||
void vu0ExecMicro(u32 addr) {
|
||||
void __fastcall vu0ExecMicro(u32 addr) {
|
||||
VUM_LOG("vu0ExecMicro %x", addr);
|
||||
|
||||
if(VU0.VI[REG_VPU_STAT].UL & 0x1) {
|
||||
|
|
|
@ -46,7 +46,7 @@ void vu1ResetRegs()
|
|||
|
||||
static int count;
|
||||
|
||||
void vu1ExecMicro(u32 addr)
|
||||
void __fastcall vu1ExecMicro(u32 addr)
|
||||
{
|
||||
while(VU0.VI[REG_VPU_STAT].UL & 0x100)
|
||||
{
|
||||
|
|
|
@ -119,14 +119,14 @@ extern void (*VU1regs_UPPER_FD_11_TABLE[32])(_VURegsNum *VUregsn);
|
|||
|
||||
// VU0
|
||||
extern void vu0ResetRegs();
|
||||
extern void vu0ExecMicro(u32 addr);
|
||||
extern void __fastcall vu0ExecMicro(u32 addr);
|
||||
extern void vu0Exec(VURegs* VU);
|
||||
extern void vu0Finish();
|
||||
extern void recResetVU0( void );
|
||||
|
||||
// VU1
|
||||
extern void vu1ResetRegs();
|
||||
extern void vu1ExecMicro(u32 addr);
|
||||
extern void __fastcall vu1ExecMicro(u32 addr);
|
||||
extern void vu1Exec(VURegs* VU);
|
||||
|
||||
void VU0_UPPER_FD_00();
|
||||
|
|
|
@ -22,7 +22,6 @@ SuperVUExecuteProgram:
|
|||
add esp, 4
|
||||
mov dword ptr [s_callstack], eax
|
||||
call SuperVUGetProgram
|
||||
mov s_vu1ebp, ebp
|
||||
mov s_vu1esi, esi
|
||||
mov s_vuedi, edi
|
||||
mov s_vuebx, ebx
|
||||
|
@ -39,7 +38,6 @@ SuperVUExecuteProgram:
|
|||
SuperVUEndProgram:
|
||||
// restore cpu state
|
||||
ldmxcsr g_sseMXCSR
|
||||
mov ebp, s_vu1ebp
|
||||
mov esi, s_vu1esi
|
||||
mov edi, s_vuedi
|
||||
mov ebx, s_vuebx
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "iCOP0.h"
|
||||
|
||||
namespace Interp = R5900::Interpreter::OpcodeImpl::COP0;
|
||||
using namespace x86Emitter;
|
||||
|
||||
namespace R5900 {
|
||||
namespace Dynarec {
|
||||
|
@ -163,12 +164,14 @@ void recMFC0( void )
|
|||
break;
|
||||
|
||||
case 1:
|
||||
CALLFunc( (uptr)COP0_UpdatePCCR );
|
||||
MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr0);
|
||||
iFlushCall(FLUSH_NODESTROY);
|
||||
xCALL( COP0_UpdatePCCR );
|
||||
xMOV(eax, &cpuRegs.PERF.n.pcr0);
|
||||
break;
|
||||
case 3:
|
||||
CALLFunc( (uptr)COP0_UpdatePCCR );
|
||||
MOV32MtoR(EAX, (uptr)&cpuRegs.PERF.n.pcr1);
|
||||
iFlushCall(FLUSH_NODESTROY);
|
||||
xCALL( COP0_UpdatePCCR );
|
||||
xMOV(eax, &cpuRegs.PERF.n.pcr1);
|
||||
break;
|
||||
}
|
||||
_deleteEEreg(_Rt_, 0);
|
||||
|
@ -240,8 +243,8 @@ void recMTC0()
|
|||
{
|
||||
case 12:
|
||||
iFlushCall(FLUSH_NODESTROY);
|
||||
//_flushCachedRegs(); //NOTE: necessary?
|
||||
_callFunctionArg1((uptr)WriteCP0Status, MEM_CONSTTAG, g_cpuConstRegs[_Rt_].UL[0]);
|
||||
xMOV( ecx, g_cpuConstRegs[_Rt_].UL[0] );
|
||||
xCALL( WriteCP0Status );
|
||||
break;
|
||||
|
||||
case 9:
|
||||
|
@ -254,9 +257,10 @@ void recMTC0()
|
|||
switch(_Imm_ & 0x3F)
|
||||
{
|
||||
case 0:
|
||||
CALLFunc( (uptr)COP0_UpdatePCCR );
|
||||
MOV32ItoM((uptr)&cpuRegs.PERF.n.pccr, g_cpuConstRegs[_Rt_].UL[0]);
|
||||
CALLFunc( (uptr)COP0_DiagnosticPCCR );
|
||||
iFlushCall(FLUSH_NODESTROY);
|
||||
xCALL( COP0_UpdatePCCR );
|
||||
xMOV( ptr32[&cpuRegs.PERF.n.pccr], g_cpuConstRegs[_Rt_].UL[0] );
|
||||
xCALL( COP0_DiagnosticPCCR );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
@ -288,8 +292,8 @@ void recMTC0()
|
|||
{
|
||||
case 12:
|
||||
iFlushCall(FLUSH_NODESTROY);
|
||||
//_flushCachedRegs(); //NOTE: necessary?
|
||||
_callFunctionArg1((uptr)WriteCP0Status, MEM_GPRTAG|_Rt_, 0);
|
||||
_eeMoveGPRtoR(ECX, _Rt_);
|
||||
xCALL( WriteCP0Status );
|
||||
break;
|
||||
|
||||
case 9:
|
||||
|
@ -302,9 +306,10 @@ void recMTC0()
|
|||
switch(_Imm_ & 0x3F)
|
||||
{
|
||||
case 0:
|
||||
CALLFunc( (uptr)COP0_UpdatePCCR );
|
||||
iFlushCall(FLUSH_NODESTROY);
|
||||
xCALL( COP0_UpdatePCCR );
|
||||
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pccr, _Rt_);
|
||||
CALLFunc( (uptr)COP0_DiagnosticPCCR );
|
||||
xCALL( COP0_DiagnosticPCCR );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
|
|
@ -136,11 +136,13 @@ static void recCTC2(s32 info)
|
|||
MOV16ItoM((uptr)&VU0.VI[REG_FBRST].UL,g_cpuConstRegs[_Rt_].UL[0]&0x0c0c);
|
||||
break;
|
||||
case REG_CMSAR1: // REG_CMSAR1
|
||||
iFlushCall(FLUSH_NOCONST);// since CALLFunc
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
assert( _checkX86reg(X86TYPE_VI, REG_VPU_STAT, 0) < 0 &&
|
||||
_checkX86reg(X86TYPE_VI, REG_TPC, 0) < 0 );
|
||||
// Execute VU1 Micro SubRoutine
|
||||
_callFunctionArg1((uptr)vu1ExecMicro, MEM_CONSTTAG, g_cpuConstRegs[_Rt_].UL[0]&0xffff);
|
||||
|
||||
xMOV( ecx, g_cpuConstRegs[_Rt_].UL[0]&0xffff );
|
||||
xCALL( vu1ExecMicro );
|
||||
break;
|
||||
default:
|
||||
{
|
||||
|
@ -191,10 +193,10 @@ static void recCTC2(s32 info)
|
|||
AND32ItoR(EAX,0x0C0C);
|
||||
MOV16RtoM((uptr)&VU0.VI[REG_FBRST].UL,EAX);
|
||||
break;
|
||||
case REG_CMSAR1: // REG_CMSAR1
|
||||
case REG_CMSAR1: // REG_CMSAR1 (Execute VU1micro Subroutine)
|
||||
iFlushCall(FLUSH_NOCONST);
|
||||
_eeMoveGPRtoR(EAX, _Rt_);
|
||||
_callFunctionArg1((uptr)vu1ExecMicro, MEM_X86TAG|EAX, 0); // Execute VU1 Micro SubRoutine
|
||||
_eeMoveGPRtoR(ECX, _Rt_);
|
||||
xCALL( vu1ExecMicro );
|
||||
break;
|
||||
default:
|
||||
_eeMoveGPRtoM((uptr)&VU0.VI[_Fs_].UL,_Rt_);
|
||||
|
|
|
@ -187,8 +187,6 @@ u8 _hasFreeXMMreg();
|
|||
void _freeXMMregs();
|
||||
int _getNumXMMwrite();
|
||||
|
||||
// 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
|
||||
|
@ -196,41 +194,8 @@ void _signExtendSFtoM(u32 mem);
|
|||
// a negative shift is for sign extension
|
||||
int _signExtendXMMtoM(u32 to, x86SSERegType from, int candestroy); // returns true if reg destroyed
|
||||
|
||||
// Defines for passing register info
|
||||
|
||||
// only valid during writes. If write128, then upper 64bits are in an mmxreg
|
||||
// (mmreg&0xf). Constant is used from gprreg ((mmreg>>16)&0x1f)
|
||||
enum memtag
|
||||
{
|
||||
MEM_EECONSTTAG = 0x0100, // argument is a GPR and comes from g_cpuConstRegs
|
||||
MEM_PSXCONSTTAG = 0x0200,
|
||||
MEM_MEMORYTAG = 0x0400,
|
||||
MEM_MMXTAG = 0x0800, // mmreg is mmxreg
|
||||
MEM_XMMTAG = 0x8000, // mmreg is xmmreg
|
||||
MEM_X86TAG = 0x4000, // ignored most of the time
|
||||
MEM_GPRTAG = 0x2000, // argument is a GPR reg
|
||||
MEM_CONSTTAG = 0x1000 // argument is a const
|
||||
};
|
||||
|
||||
template<memtag tag> static __forceinline bool IS_REG(s32 reg)
|
||||
{
|
||||
return ((reg >= 0) && (reg & tag));
|
||||
}
|
||||
|
||||
template<memtag tag> static __forceinline bool IS_REG(u32 reg)
|
||||
{
|
||||
return !!(reg & tag);
|
||||
}
|
||||
|
||||
#define IS_EECONSTREG(reg) IS_REG<MEM_EECONSTTAG>(reg)
|
||||
#define IS_PSXCONSTREG(reg) IS_REG<MEM_PSXCONSTTAG>(reg)
|
||||
#define IS_MMXREG(reg) IS_REG<MEM_MMXTAG>(reg)
|
||||
#define IS_XMMREG(reg) IS_REG<MEM_XMMTAG>(reg)
|
||||
|
||||
#define IS_X86REG(reg) IS_REG<MEM_X86TAG>(reg)
|
||||
#define IS_GPRREG(reg) IS_REG<MEM_GPRTAG>(reg)
|
||||
#define IS_CONSTREG(reg) IS_REG<MEM_CONSTTAG>(reg)
|
||||
#define IS_MEMORYREG(reg) IS_REG<MEM_MEMORYTAG>(reg)
|
||||
static const int MEM_MMXTAG = 0x002; // mmreg is mmxreg
|
||||
static const int MEM_XMMTAG = 0x004; // mmreg is xmmreg
|
||||
|
||||
//////////////////////
|
||||
// Instruction Info //
|
||||
|
@ -425,12 +390,6 @@ extern u16 x86FpuState;
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
|
||||
|
|
|
@ -350,7 +350,10 @@ void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr)
|
|||
|
||||
void _psxFlushCall(int flushtype)
|
||||
{
|
||||
_freeX86regs();
|
||||
// x86-32 ABI : These registers are not preserved across calls:
|
||||
_freeX86reg( EAX );
|
||||
_freeX86reg( ECX );
|
||||
_freeX86reg( EDX );
|
||||
|
||||
if( flushtype & FLUSH_CACHED_REGS )
|
||||
_psxFlushConstRegs();
|
||||
|
@ -436,11 +439,6 @@ void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
|
|||
_psxFlushCall(FLUSH_NODESTROY);
|
||||
CALLFunc((uptr)zeroEx);
|
||||
}
|
||||
// Bios Call: Force the IOP to do a Branch Test ASAP.
|
||||
// Important! This helps prevent game freeze-ups during boot-up and stage loads.
|
||||
// Note: Fixes to cdvd have removed the need for this code.
|
||||
//MOV32MtoR( EAX, (uptr)&psxRegs.cycle );
|
||||
//MOV32RtoM( (uptr)&g_psxNextBranchCycle, EAX );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -846,7 +844,9 @@ void rpsxSYSCALL()
|
|||
MOV32ItoM((uptr)&psxRegs.pc, psxpc - 4);
|
||||
_psxFlushCall(FLUSH_NODESTROY);
|
||||
|
||||
_callFunctionArg2((uptr)psxException, MEM_CONSTTAG, MEM_CONSTTAG, 0x20, psxbranch==1);
|
||||
xMOV( ecx, 0x20 ); // exception code
|
||||
xMOV( edx, psxbranch==1 ); // branch delay slot?
|
||||
xCALL( psxException );
|
||||
|
||||
CMP32ItoM((uptr)&psxRegs.pc, psxpc-4);
|
||||
j8Ptr[0] = JE8(0);
|
||||
|
@ -867,7 +867,9 @@ void rpsxBREAK()
|
|||
MOV32ItoM((uptr)&psxRegs.pc, psxpc - 4);
|
||||
_psxFlushCall(FLUSH_NODESTROY);
|
||||
|
||||
_callFunctionArg2((uptr)psxBREAK, MEM_CONSTTAG, MEM_CONSTTAG, 0x24, psxbranch==1);
|
||||
xMOV( ecx, 0x24 ); // exception code
|
||||
xMOV( edx, psxbranch==1 ); // branch delay slot?
|
||||
xCALL( psxException );
|
||||
|
||||
CMP32ItoM((uptr)&psxRegs.pc, psxpc-4);
|
||||
j8Ptr[0] = JE8(0);
|
||||
|
|
|
@ -594,321 +594,23 @@ void rpsxDIVU_(int info) { rpsxDIVsuper(info, 0); }
|
|||
|
||||
PSXRECOMPILE_CONSTCODE3_PENALTY(DIVU, 1, psxInstCycles_Div);
|
||||
|
||||
//// LoadStores
|
||||
#ifdef PCSX2_VIRTUAL_MEM
|
||||
|
||||
// VM load store functions (fastest)
|
||||
|
||||
//#define REC_SLOWREAD
|
||||
//#define REC_SLOWWRITE
|
||||
|
||||
int _psxPrepareReg(int gprreg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 s_nAddMemOffset = 0;
|
||||
|
||||
static __forceinline void SET_HWLOC_R3000A() {
|
||||
x86SetJ8(j8Ptr[0]);
|
||||
SHR32ItoR(ECX, 3);
|
||||
if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset);
|
||||
}
|
||||
|
||||
int rpsxSetMemLocation(int regs, int mmreg)
|
||||
{
|
||||
s_nAddMemOffset = 0;
|
||||
MOV32MtoR( ECX, (int)&psxRegs.GPR.r[ regs ] );
|
||||
|
||||
if ( _Imm_ != 0 ) ADD32ItoR( ECX, _Imm_ );
|
||||
|
||||
SHL32ItoR(ECX, 3);
|
||||
j8Ptr[0] = JS8(0);
|
||||
SHR32ItoR(ECX, 3);
|
||||
AND32ItoR(ECX, 0x1fffff); // 2Mb
|
||||
return 1;
|
||||
}
|
||||
|
||||
void recLoad32(u32 bit, u32 sign)
|
||||
{
|
||||
int mmreg = -1;
|
||||
|
||||
#ifdef REC_SLOWREAD
|
||||
_psxFlushConstReg(_Rs_);
|
||||
#else
|
||||
if( PSX_IS_CONST1( _Rs_ ) ) {
|
||||
// do const processing
|
||||
int ineax = 0;
|
||||
|
||||
_psxOnWriteReg(_Rt_);
|
||||
mmreg = EAX;
|
||||
|
||||
switch(bit) {
|
||||
case 8: ineax = psxRecMemConstRead8(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign); break;
|
||||
case 16:
|
||||
assert( (g_psxConstRegs[_Rs_]+_Imm_) % 2 == 0 );
|
||||
ineax = psxRecMemConstRead16(mmreg, g_psxConstRegs[_Rs_]+_Imm_, sign);
|
||||
break;
|
||||
case 32:
|
||||
assert( (g_psxConstRegs[_Rs_]+_Imm_) % 4 == 0 );
|
||||
ineax = psxRecMemConstRead32(mmreg, g_psxConstRegs[_Rs_]+_Imm_);
|
||||
break;
|
||||
}
|
||||
|
||||
if( _Rt_ ) MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int dohw;
|
||||
int mmregs = _psxPrepareReg(_Rs_);
|
||||
|
||||
_psxOnWriteReg(_Rt_);
|
||||
_psxDeleteReg(_Rt_, 0);
|
||||
|
||||
dohw = rpsxSetMemLocation(_Rs_, mmregs);
|
||||
|
||||
switch(bit) {
|
||||
case 8:
|
||||
if( sign ) MOVSX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset);
|
||||
else MOVZX32Rm8toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset);
|
||||
break;
|
||||
case 16:
|
||||
if( sign ) MOVSX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset);
|
||||
else MOVZX32Rm16toROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset);
|
||||
break;
|
||||
case 32:
|
||||
MOV32RmtoROffset(EAX, ECX, PS2MEM_PSX_+s_nAddMemOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
if( dohw ) {
|
||||
j8Ptr[1] = JMP8(0);
|
||||
|
||||
SET_HWLOC_R3000A();
|
||||
|
||||
switch(bit) {
|
||||
case 8:
|
||||
CALLFunc( (int)psxRecMemRead8 );
|
||||
if( sign ) MOVSX32R8toR(EAX, EAX);
|
||||
else MOVZX32R8toR(EAX, EAX);
|
||||
break;
|
||||
case 16:
|
||||
CALLFunc( (int)psxRecMemRead16 );
|
||||
if( sign ) MOVSX32R16toR(EAX, EAX);
|
||||
else MOVZX32R16toR(EAX, EAX);
|
||||
break;
|
||||
case 32:
|
||||
CALLFunc( (int)psxRecMemRead32 );
|
||||
break;
|
||||
}
|
||||
|
||||
x86SetJ8(j8Ptr[1]);
|
||||
}
|
||||
|
||||
if( _Rt_ )
|
||||
MOV32RtoM( (int)&psxRegs.GPR.r[ _Rt_ ], EAX );
|
||||
}
|
||||
}
|
||||
|
||||
void rpsxLB() { recLoad32(8, 1); }
|
||||
void rpsxLBU() { recLoad32(8, 0); }
|
||||
void rpsxLH() { recLoad32(16, 1); }
|
||||
void rpsxLHU() { recLoad32(16, 0); }
|
||||
void rpsxLW() { recLoad32(32, 0); }
|
||||
|
||||
extern void rpsxMemConstClear(u32 mem);
|
||||
|
||||
// check if mem is executable, and clear it
|
||||
__declspec(naked) void rpsxWriteMemClear()
|
||||
{
|
||||
_asm {
|
||||
mov edx, ecx
|
||||
shr edx, 14
|
||||
and dl, 0xfc
|
||||
add edx, psxRecLUT
|
||||
test dword ptr [edx], 0xffffffff
|
||||
jnz Clear32
|
||||
ret
|
||||
Clear32:
|
||||
// recLUT[mem>>16] + (mem&0xfffc)
|
||||
mov edx, dword ptr [edx]
|
||||
mov eax, ecx
|
||||
and eax, 0xfffc
|
||||
// edx += 2*eax
|
||||
shl eax, 1
|
||||
add edx, eax
|
||||
cmp dword ptr [edx], 0
|
||||
je ClearRet
|
||||
sub esp, 4
|
||||
mov dword ptr [esp], edx
|
||||
call psxRecClearMem
|
||||
add esp, 4
|
||||
ClearRet:
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
extern u32 s_psxBlockCycles;
|
||||
void recStore(int bit)
|
||||
{
|
||||
#ifdef REC_SLOWWRITE
|
||||
_psxFlushConstReg(_Rs_);
|
||||
#else
|
||||
if( PSX_IS_CONST1( _Rs_ ) ) {
|
||||
u8* pjmpok;
|
||||
u32 addr = g_psxConstRegs[_Rs_]+_Imm_;
|
||||
int doclear = 0;
|
||||
|
||||
if( !(addr & 0x10000000) ) {
|
||||
// check g_psxWriteOk
|
||||
CMP32ItoM((uptr)&g_psxWriteOk, 0);
|
||||
pjmpok = JE8(0);
|
||||
}
|
||||
|
||||
switch(bit) {
|
||||
case 8:
|
||||
if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite8(addr, MEM_PSXCONSTTAG|(_Rt_<<16));
|
||||
else {
|
||||
_psxMoveGPRtoR(EAX, _Rt_);
|
||||
doclear = psxRecMemConstWrite8(addr, EAX);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 16:
|
||||
assert( (addr)%2 == 0 );
|
||||
if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite16(addr, MEM_PSXCONSTTAG|(_Rt_<<16));
|
||||
else {
|
||||
_psxMoveGPRtoR(EAX, _Rt_);
|
||||
doclear = psxRecMemConstWrite16(addr, EAX);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 32:
|
||||
assert( (addr)%4 == 0 );
|
||||
if( PSX_IS_CONST1(_Rt_) ) doclear = psxRecMemConstWrite32(addr, MEM_PSXCONSTTAG|(_Rt_<<16));
|
||||
else {
|
||||
_psxMoveGPRtoR(EAX, _Rt_);
|
||||
doclear = psxRecMemConstWrite32(addr, EAX);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( !(addr & 0x10000000) ) {
|
||||
if( doclear ) rpsxMemConstClear((addr)&~3);
|
||||
x86SetJ8(pjmpok);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int dohw;
|
||||
int mmregs = _psxPrepareReg(_Rs_);
|
||||
dohw = rpsxSetMemLocation(_Rs_, mmregs);
|
||||
|
||||
CMP32ItoM((uptr)&g_psxWriteOk, 0);
|
||||
u8* pjmpok = JE8(0);
|
||||
|
||||
if( PSX_IS_CONST1( _Rt_ ) ) {
|
||||
switch(bit) {
|
||||
case 8: MOV8ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break;
|
||||
case 16: MOV16ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break;
|
||||
case 32: MOV32ItoRmOffset(ECX, g_psxConstRegs[_Rt_], PS2MEM_PSX_+s_nAddMemOffset); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(bit) {
|
||||
case 8:
|
||||
MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]);
|
||||
MOV8RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]);
|
||||
MOV16RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]);
|
||||
MOV32RtoRmOffset(ECX, EAX, PS2MEM_PSX_+s_nAddMemOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( s_nAddMemOffset ) ADD32ItoR(ECX, s_nAddMemOffset);
|
||||
CMP32MtoR(ECX, (uptr)&g_psxMaxRecMem);
|
||||
|
||||
j8Ptr[1] = JAE8(0);
|
||||
|
||||
if( bit < 32 ) AND8ItoR(ECX, 0xfc);
|
||||
CALLFunc((u32)rpsxWriteMemClear);
|
||||
|
||||
if( dohw ) {
|
||||
j8Ptr[2] = JMP8(0);
|
||||
|
||||
SET_HWLOC_R3000A();
|
||||
|
||||
if( PSX_IS_CONST1(_Rt_) ) {
|
||||
switch(bit) {
|
||||
case 8: MOV8ItoR(EAX, g_psxConstRegs[_Rt_]); break;
|
||||
case 16: MOV16ItoR(EAX, g_psxConstRegs[_Rt_]); break;
|
||||
case 32: MOV32ItoR(EAX, g_psxConstRegs[_Rt_]); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(bit) {
|
||||
case 8: MOV8MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break;
|
||||
case 16: MOV16MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break;
|
||||
case 32: MOV32MtoR(EAX, (int)&psxRegs.GPR.r[ _Rt_ ]); break;
|
||||
}
|
||||
}
|
||||
|
||||
if( s_nAddMemOffset != 0 ) ADD32ItoR(ECX, s_nAddMemOffset);
|
||||
|
||||
// some type of hardware write
|
||||
switch(bit) {
|
||||
case 8: CALLFunc( (int)psxRecMemWrite8 ); break;
|
||||
case 16: CALLFunc( (int)psxRecMemWrite16 ); break;
|
||||
case 32: CALLFunc( (int)psxRecMemWrite32 ); break;
|
||||
}
|
||||
|
||||
x86SetJ8(j8Ptr[2]);
|
||||
}
|
||||
|
||||
x86SetJ8(j8Ptr[1]);
|
||||
x86SetJ8(pjmpok);
|
||||
}
|
||||
}
|
||||
|
||||
void rpsxSB() { recStore(8); }
|
||||
void rpsxSH() { recStore(16); }
|
||||
void rpsxSW() { recStore(32); }
|
||||
|
||||
REC_FUNC(LWL);
|
||||
REC_FUNC(LWR);
|
||||
REC_FUNC(SWL);
|
||||
REC_FUNC(SWR);
|
||||
|
||||
#else
|
||||
|
||||
// TLB loadstore functions
|
||||
REC_FUNC(LWL);
|
||||
REC_FUNC(LWR);
|
||||
REC_FUNC(SWL);
|
||||
REC_FUNC(SWR);
|
||||
|
||||
using namespace x86Emitter;
|
||||
|
||||
static void rpsxLB()
|
||||
{
|
||||
_psxDeleteReg(_Rs_, 1);
|
||||
_psxOnWriteReg(_Rt_);
|
||||
_psxDeleteReg(_Rt_, 0);
|
||||
|
||||
MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(X86ARG1, _Imm_);
|
||||
_callFunctionArg1((uptr)iopMemRead8, X86ARG1|MEM_X86TAG, 0);
|
||||
MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(ECX, _Imm_);
|
||||
xCALL( iopMemRead8 ); // returns value in EAX
|
||||
if (_Rt_) {
|
||||
MOVSX32R8toR(EAX, EAX);
|
||||
MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
|
||||
|
@ -922,9 +624,9 @@ static void rpsxLBU()
|
|||
_psxOnWriteReg(_Rt_);
|
||||
_psxDeleteReg(_Rt_, 0);
|
||||
|
||||
MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(X86ARG1, _Imm_);
|
||||
_callFunctionArg1((uptr)iopMemRead8, X86ARG1|MEM_X86TAG, 0);
|
||||
MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(ECX, _Imm_);
|
||||
xCALL( iopMemRead8 ); // returns value in EAX
|
||||
if (_Rt_) {
|
||||
MOVZX32R8toR(EAX, EAX);
|
||||
MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
|
||||
|
@ -938,9 +640,9 @@ static void rpsxLH()
|
|||
_psxOnWriteReg(_Rt_);
|
||||
_psxDeleteReg(_Rt_, 0);
|
||||
|
||||
MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(X86ARG1, _Imm_);
|
||||
_callFunctionArg1((uptr)iopMemRead16, X86ARG1|MEM_X86TAG, 0);
|
||||
MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(ECX, _Imm_);
|
||||
xCALL( iopMemRead16 ); // returns value in EAX
|
||||
if (_Rt_) {
|
||||
MOVSX32R16toR(EAX, EAX);
|
||||
MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
|
||||
|
@ -954,9 +656,9 @@ static void rpsxLHU()
|
|||
_psxOnWriteReg(_Rt_);
|
||||
_psxDeleteReg(_Rt_, 0);
|
||||
|
||||
MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(X86ARG1, _Imm_);
|
||||
_callFunctionArg1((uptr)iopMemRead16, X86ARG1|MEM_X86TAG, 0);
|
||||
MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(ECX, _Imm_);
|
||||
xCALL( iopMemRead16 ); // returns value in EAX
|
||||
if (_Rt_) {
|
||||
MOVZX32R16toR(EAX, EAX);
|
||||
MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
|
||||
|
@ -971,13 +673,13 @@ static void rpsxLW()
|
|||
_psxDeleteReg(_Rt_, 0);
|
||||
|
||||
_psxFlushCall(FLUSH_EVERYTHING);
|
||||
MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(X86ARG1, _Imm_);
|
||||
MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(ECX, _Imm_);
|
||||
|
||||
TEST32ItoR(X86ARG1, 0x10000000);
|
||||
TEST32ItoR(ECX, 0x10000000);
|
||||
j8Ptr[0] = JZ8(0);
|
||||
|
||||
_callFunctionArg1((uptr)iopMemRead32, X86ARG1|MEM_X86TAG, 0);
|
||||
xCALL( iopMemRead32 ); // returns value in EAX
|
||||
if (_Rt_) {
|
||||
MOV32RtoM((uptr)&psxRegs.GPR.r[_Rt_], EAX);
|
||||
}
|
||||
|
@ -985,11 +687,11 @@ static void rpsxLW()
|
|||
x86SetJ8(j8Ptr[0]);
|
||||
|
||||
// read from psM directly
|
||||
AND32ItoR(X86ARG1, 0x1fffff);
|
||||
ADD32ItoR(X86ARG1, (uptr)psxM);
|
||||
AND32ItoR(ECX, 0x1fffff);
|
||||
ADD32ItoR(ECX, (uptr)psxM);
|
||||
|
||||
MOV32RmtoR( X86ARG1, X86ARG1 );
|
||||
MOV32RtoM( (uptr)&psxRegs.GPR.r[_Rt_], X86ARG1);
|
||||
MOV32RmtoR( ECX, ECX );
|
||||
MOV32RtoM( (uptr)&psxRegs.GPR.r[_Rt_], ECX);
|
||||
|
||||
x86SetJ8(j8Ptr[1]);
|
||||
PSX_DEL_CONST(_Rt_);
|
||||
|
@ -1000,9 +702,10 @@ static void rpsxSB()
|
|||
_psxDeleteReg(_Rs_, 1);
|
||||
_psxDeleteReg(_Rt_, 1);
|
||||
|
||||
MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(X86ARG1, _Imm_);
|
||||
_callFunctionArg2((uptr)iopMemWrite8, X86ARG1|MEM_X86TAG, MEM_MEMORYTAG, 0, (uptr)&psxRegs.GPR.r[_Rt_]);
|
||||
MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(ECX, _Imm_);
|
||||
xMOV( edx, &psxRegs.GPR.r[_Rt_] );
|
||||
xCALL( iopMemWrite8 );
|
||||
}
|
||||
|
||||
static void rpsxSH()
|
||||
|
@ -1010,9 +713,10 @@ static void rpsxSH()
|
|||
_psxDeleteReg(_Rs_, 1);
|
||||
_psxDeleteReg(_Rt_, 1);
|
||||
|
||||
MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(X86ARG1, _Imm_);
|
||||
_callFunctionArg2((uptr)iopMemWrite16, X86ARG1|MEM_X86TAG, MEM_MEMORYTAG, 0, (uptr)&psxRegs.GPR.r[_Rt_]);
|
||||
MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(ECX, _Imm_);
|
||||
xMOV( edx, &psxRegs.GPR.r[_Rt_] );
|
||||
xCALL( iopMemWrite16 );
|
||||
}
|
||||
|
||||
static void rpsxSW()
|
||||
|
@ -1020,13 +724,12 @@ static void rpsxSW()
|
|||
_psxDeleteReg(_Rs_, 1);
|
||||
_psxDeleteReg(_Rt_, 1);
|
||||
|
||||
MOV32MtoR(X86ARG1, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(X86ARG1, _Imm_);
|
||||
_callFunctionArg2((uptr)iopMemWrite32, X86ARG1|MEM_X86TAG, MEM_MEMORYTAG, 0, (uptr)&psxRegs.GPR.r[_Rt_]);
|
||||
MOV32MtoR(ECX, (uptr)&psxRegs.GPR.r[_Rs_]);
|
||||
if (_Imm_) ADD32ItoR(ECX, _Imm_);
|
||||
xMOV( edx, &psxRegs.GPR.r[_Rt_] );
|
||||
xCALL( iopMemWrite32 );
|
||||
}
|
||||
|
||||
#endif // end load store
|
||||
|
||||
//// SLL
|
||||
void rpsxSLL_const()
|
||||
{
|
||||
|
|
|
@ -236,7 +236,8 @@ void _flushConstRegs()
|
|||
int _allocX86reg(int x86reg, int type, int reg, int mode)
|
||||
{
|
||||
int i;
|
||||
assert( reg >= 0 && reg < 32 );
|
||||
pxAssertDev( reg >= 0 && reg < 32, "Register index out of bounds." );
|
||||
pxAssertDev( x86reg != ESP && x86reg != EBP, "Allocation of ESP/EBP is not allowed!" );
|
||||
|
||||
// don't alloc EAX and ESP,EBP if MODE_NOFRAME
|
||||
int oldmode = mode;
|
||||
|
@ -448,14 +449,10 @@ void _freeX86reg(int x86reg)
|
|||
x86regs[x86reg].inuse = 0;
|
||||
}
|
||||
|
||||
void _freeX86regs() {
|
||||
int i;
|
||||
|
||||
for (i=0; i<iREGCNT_GPR; i++) {
|
||||
if (!x86regs[i].inuse) continue;
|
||||
|
||||
void _freeX86regs()
|
||||
{
|
||||
for (int i=0; i<iREGCNT_GPR; i++)
|
||||
_freeX86reg(i);
|
||||
}
|
||||
}
|
||||
|
||||
// MMX Caching
|
||||
|
@ -863,88 +860,6 @@ void SetFPUstate() {
|
|||
}
|
||||
}
|
||||
|
||||
__forceinline void _callPushArg(u32 arg, uptr argmem)
|
||||
{
|
||||
if( IS_X86REG(arg) ) {
|
||||
PUSH32R(arg&0xff);
|
||||
}
|
||||
else if( IS_CONSTREG(arg) ) {
|
||||
PUSH32I(argmem);
|
||||
}
|
||||
else if( IS_GPRREG(arg) ) {
|
||||
SUB32ItoR(ESP, 4);
|
||||
_eeMoveGPRtoRm(ESP, arg&0xff);
|
||||
}
|
||||
else if( IS_XMMREG(arg) ) {
|
||||
SUB32ItoR(ESP, 4);
|
||||
SSEX_MOVD_XMM_to_Rm(ESP, arg&0xf);
|
||||
}
|
||||
else if( IS_MMXREG(arg) ) {
|
||||
SUB32ItoR(ESP, 4);
|
||||
MOVD32MMXtoRm(ESP, arg&0xf);
|
||||
}
|
||||
else if( IS_EECONSTREG(arg) ) {
|
||||
PUSH32I(g_cpuConstRegs[(arg>>16)&0x1f].UL[0]);
|
||||
}
|
||||
else if( IS_PSXCONSTREG(arg) ) {
|
||||
PUSH32I(g_psxConstRegs[(arg>>16)&0x1f]);
|
||||
}
|
||||
else if( IS_MEMORYREG(arg) ) {
|
||||
PUSH32M(argmem);
|
||||
}
|
||||
else {
|
||||
assert( (arg&0xfff0) == 0 );
|
||||
// assume it is a GPR reg
|
||||
PUSH32R(arg&0xf);
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void _callFunctionArg1(uptr fn, u32 arg1, uptr arg1mem)
|
||||
{
|
||||
_callPushArg(arg1, arg1mem);
|
||||
CALLFunc((uptr)fn);
|
||||
ADD32ItoR(ESP, 4);
|
||||
}
|
||||
|
||||
__forceinline void _callFunctionArg2(uptr fn, u32 arg1, u32 arg2, uptr arg1mem, uptr arg2mem)
|
||||
{
|
||||
_callPushArg(arg2, arg2mem);
|
||||
_callPushArg(arg1, arg1mem);
|
||||
CALLFunc((uptr)fn);
|
||||
ADD32ItoR(ESP, 8);
|
||||
}
|
||||
|
||||
__forceinline void _callFunctionArg3(uptr fn, u32 arg1, u32 arg2, u32 arg3, uptr arg1mem, uptr arg2mem, uptr arg3mem)
|
||||
{
|
||||
_callPushArg(arg3, arg3mem);
|
||||
_callPushArg(arg2, arg2mem);
|
||||
_callPushArg(arg1, arg1mem);
|
||||
CALLFunc((uptr)fn);
|
||||
ADD32ItoR(ESP, 12);
|
||||
}
|
||||
|
||||
void _recPushReg(int mmreg)
|
||||
{
|
||||
if( IS_XMMREG(mmreg) ) {
|
||||
SUB32ItoR(ESP, 4);
|
||||
SSEX_MOVD_XMM_to_Rm(ESP, mmreg&0xf);
|
||||
}
|
||||
else if( IS_MMXREG(mmreg) ) {
|
||||
SUB32ItoR(ESP, 4);
|
||||
MOVD32MMXtoRm(ESP, mmreg&0xf);
|
||||
}
|
||||
else if( IS_EECONSTREG(mmreg) ) {
|
||||
PUSH32I(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]);
|
||||
}
|
||||
else if( IS_PSXCONSTREG(mmreg) ) {
|
||||
PUSH32I(g_psxConstRegs[(mmreg>>16)&0x1f]);
|
||||
}
|
||||
else {
|
||||
assert( (mmreg&0xfff0) == 0 );
|
||||
PUSH32R(mmreg);
|
||||
}
|
||||
}
|
||||
|
||||
void _signExtendSFtoM(u32 mem)
|
||||
{
|
||||
LAHF();
|
||||
|
|
|
@ -371,7 +371,7 @@ static void _DynGen_StackFrameCheck()
|
|||
xCMP( esp, &s_store_esp );
|
||||
xForwardJE8 skipassert_esp;
|
||||
|
||||
xXOR( ecx, ecx ); // 0 specifies ESI
|
||||
xXOR( ecx, ecx ); // 0 specifies ESP
|
||||
xMOV( edx, esp );
|
||||
xCALL( StackFrameCheckFailed );
|
||||
xMOV( esp, &s_store_esp ); // half-hearted frame recovery attempt!
|
||||
|
@ -867,6 +867,12 @@ void CheckForBIOSEnd()
|
|||
{
|
||||
xMOV( eax, &cpuRegs.pc );
|
||||
|
||||
/*xCMP( eax, 0x00200008 );
|
||||
xJE(ExitRec);
|
||||
|
||||
xCMP( eax, 0x00100008 );
|
||||
xJE(ExitRec);*/
|
||||
|
||||
xCMP( eax, 0x00200008 );
|
||||
xForwardJE8 CallExitRec;
|
||||
|
||||
|
@ -975,7 +981,10 @@ void LoadBranchState()
|
|||
|
||||
void iFlushCall(int flushtype)
|
||||
{
|
||||
_freeX86regs();
|
||||
// Free registers that are not saved across function calls (x86-32 ABI):
|
||||
_freeX86reg(EAX);
|
||||
_freeX86reg(ECX);
|
||||
_freeX86reg(EDX);
|
||||
|
||||
if( flushtype & FLUSH_FREE_XMM )
|
||||
_freeXMMregs();
|
||||
|
@ -1076,6 +1085,8 @@ static u32 eeScaleBlockCycles()
|
|||
// setting "branch = 2";
|
||||
static void iBranchTest(u32 newpc)
|
||||
{
|
||||
_DynGen_StackFrameCheck();
|
||||
|
||||
if( g_ExecBiosHack ) CheckForBIOSEnd();
|
||||
|
||||
// Check the Event scheduler if our "cycle target" has been reached.
|
||||
|
@ -1306,7 +1317,7 @@ void __fastcall dyna_block_discard(u32 start,u32 sz)
|
|||
// EBP/stackframe before issuing a RET, else esp/ebp will be incorrect.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm leave; __asm jmp [ExitRecompiledCode]
|
||||
__asm leave __asm jmp [ExitRecompiledCode]
|
||||
#else
|
||||
__asm__ __volatile__( "leave\n jmp *%[exitRec]\n" : : [exitRec] "m" (ExitRecompiledCode) : );
|
||||
#endif
|
||||
|
@ -1321,7 +1332,7 @@ void __fastcall dyna_page_reset(u32 start,u32 sz)
|
|||
mmap_MarkCountedRamPage( start );
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm leave; __asm jmp [ExitRecompiledCode]
|
||||
__asm leave __asm jmp [ExitRecompiledCode]
|
||||
#else
|
||||
__asm__ __volatile__( "leave\n jmp *%[exitRec]\n" : : [exitRec] "m" (ExitRecompiledCode) : );
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "iR5900.h"
|
||||
#include "R5900OpcodeTables.h"
|
||||
|
||||
using namespace x86Emitter;
|
||||
|
||||
extern void _vu0WaitMicro();
|
||||
extern void _vu0FinishMicro();
|
||||
|
||||
|
@ -311,14 +313,12 @@ static void recCTC2() {
|
|||
}
|
||||
else MOV32ItoM((uptr)µVU0.regs->VI[_Rd_].UL, 0);
|
||||
break;
|
||||
case REG_CMSAR1:
|
||||
case REG_CMSAR1: // Execute VU1 Micro SubRoutine
|
||||
if (_Rt_) {
|
||||
MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
|
||||
PUSH32R(EAX);
|
||||
MOV32MtoR(ECX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
|
||||
}
|
||||
else PUSH32I(0);
|
||||
CALLFunc((uptr)vu1ExecMicro); // Execute VU1 Micro SubRoutine
|
||||
ADD32ItoR(ESP, 4);
|
||||
else XOR32RtoR(ECX,ECX);
|
||||
xCALL(vu1ExecMicro);
|
||||
break;
|
||||
case REG_FBRST:
|
||||
if (!_Rt_) {
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "AppConfig.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace x86Emitter;
|
||||
|
||||
// temporary externs
|
||||
extern void iDumpVU0Registers();
|
||||
|
@ -2526,8 +2527,8 @@ static void SuperVUAssignRegs()
|
|||
int s_writeQ, s_writeP;
|
||||
|
||||
// declare the saved registers
|
||||
uptr s_vu1esp, s_callstack;//, s_vu1esp
|
||||
uptr s_vu1ebp, s_vuebx, s_vuedi, s_vu1esi;
|
||||
uptr s_vu1esp, s_callstack;
|
||||
uptr s_vuebx, s_vuedi, s_vu1esi;
|
||||
|
||||
static int s_recWriteQ, s_recWriteP; // wait times during recompilation
|
||||
static int s_needFlush; // first bit - Q, second bit - P, third bit - Q has been written, fourth bit - P has been written
|
||||
|
@ -2576,6 +2577,11 @@ void SuperVUCleanupProgram(u32 startpc, int vuindex)
|
|||
// entry point of all vu programs from emulator calls
|
||||
__declspec(naked) void SuperVUExecuteProgram(u32 startpc, int vuindex)
|
||||
{
|
||||
// Stackframe setup for the recompiler:
|
||||
// We rewind the stack 4 bytes, which places the parameters of this function before
|
||||
// any calls we might make from recompiled code. The return address for this function
|
||||
// call is subsequently stored in s_callstack.
|
||||
|
||||
__asm
|
||||
{
|
||||
mov eax, dword ptr [esp]
|
||||
|
@ -2585,20 +2591,15 @@ __declspec(naked) void SuperVUExecuteProgram(u32 startpc, int vuindex)
|
|||
call SuperVUGetProgram
|
||||
|
||||
// save cpu state
|
||||
mov s_vu1ebp, ebp
|
||||
mov s_vu1esi, esi // have to save even in Release
|
||||
mov s_vuedi, edi // have to save even in Release
|
||||
//mov s_vu1ebp, ebp
|
||||
mov s_vu1esi, esi
|
||||
mov s_vuedi, edi
|
||||
mov s_vuebx, ebx
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEBUG
|
||||
__asm
|
||||
{
|
||||
mov s_vu1esp, esp
|
||||
}
|
||||
#endif
|
||||
|
||||
__asm
|
||||
{
|
||||
//stmxcsr s_ssecsr
|
||||
ldmxcsr g_sseVUMXCSR
|
||||
|
||||
|
@ -2618,7 +2619,7 @@ __declspec(naked) static void SuperVUEndProgram()
|
|||
// restore cpu state
|
||||
ldmxcsr g_sseMXCSR
|
||||
|
||||
mov ebp, s_vu1ebp
|
||||
//mov ebp, s_vu1ebp
|
||||
mov esi, s_vu1esi
|
||||
mov edi, s_vuedi
|
||||
mov ebx, s_vuebx
|
||||
|
@ -3105,6 +3106,8 @@ void VuBaseBlock::Recompile()
|
|||
_x86regs* endx86 = &s_vecRegArray[nEndx86];
|
||||
for (int i = 0; i < iREGCNT_GPR; ++i)
|
||||
{
|
||||
if( i == ESP || i == EBP ) continue;
|
||||
|
||||
if (endx86[i].inuse)
|
||||
{
|
||||
|
||||
|
@ -3652,7 +3655,8 @@ void VuInstruction::Recompile(list<VuInstruction>::iterator& itinst, u32 vuxyz)
|
|||
TEST32ItoM((uptr)&VU0.VI[REG_FBRST].UL, s_vu ? 0x400 : 0x004);
|
||||
u8* ptr = JZ8(0);
|
||||
OR32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, s_vu ? 0x200 : 0x002);
|
||||
_callFunctionArg1((uptr)hwIntcIrq, MEM_CONSTTAG, s_vu ? INTC_VU1 : INTC_VU0);
|
||||
xMOV( ecx, s_vu ? INTC_VU1 : INTC_VU0 );
|
||||
xCALL( hwIntcIrq );
|
||||
x86SetJ8(ptr);
|
||||
}
|
||||
if (ptr[1] & 0x08000000) // T flag
|
||||
|
@ -3660,7 +3664,8 @@ void VuInstruction::Recompile(list<VuInstruction>::iterator& itinst, u32 vuxyz)
|
|||
TEST32ItoM((uptr)&VU0.VI[REG_FBRST].UL, s_vu ? 0x800 : 0x008);
|
||||
u8* ptr = JZ8(0);
|
||||
OR32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, s_vu ? 0x400 : 0x004);
|
||||
_callFunctionArg1((uptr)hwIntcIrq, MEM_CONSTTAG, s_vu ? INTC_VU1 : INTC_VU0);
|
||||
xMOV( ecx, s_vu ? INTC_VU1 : INTC_VU0 );
|
||||
xCALL( hwIntcIrq );
|
||||
x86SetJ8(ptr);
|
||||
}
|
||||
|
||||
|
@ -4379,7 +4384,7 @@ void recVUMI_XGKICK(VURegs *VU, int info)
|
|||
recVUMI_XGKICK_(VU);
|
||||
}
|
||||
|
||||
int isreg = _allocX86reg(X86ARG2, X86TYPE_VI | (s_vu ? X86TYPE_VU1 : 0), _Is_, MODE_READ);
|
||||
int isreg = _allocX86reg(ECX, X86TYPE_VI | (s_vu ? X86TYPE_VU1 : 0), _Is_, MODE_READ);
|
||||
_freeX86reg(isreg); // flush
|
||||
x86regs[isreg].inuse = 1;
|
||||
x86regs[isreg].type = X86TYPE_VITEMP;
|
||||
|
|
Loading…
Reference in New Issue