diff --git a/common/include/x86emitter/instructions.h b/common/include/x86emitter/instructions.h index fa3a67c3fe..00c45d95ca 100644 --- a/common/include/x86emitter/instructions.h +++ b/common/include/x86emitter/instructions.h @@ -1,6 +1,6 @@ /* PCSX2 - PS2 Emulator for PCs * Copyright (C) 2002-2009 PCSX2 Dev Team - * + * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. @@ -188,6 +188,7 @@ namespace x86Emitter // ----- Miscellaneous Instructions ----- // Various Instructions with no parameter and no special encoding logic. + extern void xLEAVE(); extern void xRET(); extern void xCBW(); extern void xCWD(); @@ -244,7 +245,7 @@ namespace x86Emitter // ------------------------------------------------------------------------ // Forward Jump Helpers (act as labels!) - + #define DEFINE_FORWARD_JUMP( label, cond ) \ template< typename OperandType > \ class xForward##label : public xForwardJump \ @@ -328,7 +329,7 @@ namespace x86Emitter DEFINE_FORWARD_JUMP( JPE, Jcc_ParityEven ); DEFINE_FORWARD_JUMP( JPO, Jcc_ParityOdd ); - + typedef xForwardJPE xForwardJPE8; typedef xForwardJPE xForwardJPE32; typedef xForwardJPO xForwardJPO8; @@ -362,7 +363,7 @@ namespace x86Emitter extern void xMOVQZX( const xRegisterSSE& to, const ModSibBase& src ); extern void xMOVQZX( const xRegisterSSE& to, const xRegisterSSE& from ); - + extern void xMOVSS( const xRegisterSSE& to, const xRegisterSSE& from ); extern void xMOVSS( const ModSibBase& to, const xRegisterSSE& from ); extern void xMOVSD( const xRegisterSSE& to, const xRegisterSSE& from ); @@ -421,12 +422,12 @@ namespace x86Emitter extern void xEXTRACTPS( const ModSibStrict& dest, const xRegisterSSE& from, u8 imm8 ); // ------------------------------------------------------------------------ - + extern const Internal::SimdImpl_DestRegEither<0x66,0xdb> xPAND; extern const Internal::SimdImpl_DestRegEither<0x66,0xdf> xPANDN; extern const Internal::SimdImpl_DestRegEither<0x66,0xeb> xPOR; extern const Internal::SimdImpl_DestRegEither<0x66,0xef> xPXOR; - + extern const Internal::SimdImpl_AndNot xANDN; extern const Internal::SimdImpl_COMI xCOMI; @@ -434,7 +435,7 @@ namespace x86Emitter extern const Internal::SimdImpl_rSqrt<0x53> xRCP; extern const Internal::SimdImpl_rSqrt<0x52> xRSQRT; extern const Internal::SimdImpl_Sqrt<0x51> xSQRT; - + extern const Internal::SimdImpl_MinMax<0x5f> xMAX; extern const Internal::SimdImpl_MinMax<0x5d> xMIN; extern const Internal::SimdImpl_Shuffle<0xc6> xSHUF; @@ -442,7 +443,7 @@ namespace x86Emitter // ------------------------------------------------------------------------ extern const Internal::SimdImpl_DestRegSSE<0x66,0x1738> xPTEST; - + extern const Internal::SimdImpl_Compare xCMPEQ; extern const Internal::SimdImpl_Compare xCMPLT; extern const Internal::SimdImpl_Compare xCMPLE; @@ -484,9 +485,9 @@ namespace x86Emitter extern const Internal::SimdImpl_DestRegStrict<0xf2,0x2c,xRegister32, xRegisterSSE,u64> xCVTTSD2SI; extern const Internal::SimdImpl_DestRegStrict<0xf3,0x2c,xRegister32, xRegisterSSE,u32> xCVTTSS2SI; - + // ------------------------------------------------------------------------ - + extern const Internal::SimdImpl_Shift<0xf0, 6> xPSLL; extern const Internal::SimdImpl_Shift<0xd0, 2> xPSRL; extern const Internal::SimdImpl_ShiftWithoutQ<0xe0, 4> xPSRA; @@ -502,7 +503,7 @@ namespace x86Emitter extern const Internal::SimdImpl_PUnpack xPUNPCK; extern const Internal::SimdImpl_Unpack xUNPCK; extern const Internal::SimdImpl_Pack xPACK; - + extern const Internal::SimdImpl_PAbsolute xPABS; extern const Internal::SimdImpl_PSign xPSIGN; extern const Internal::SimdImpl_PInsert xPINSR; @@ -513,7 +514,7 @@ namespace x86Emitter extern const Internal::SimdImpl_Blend xBLEND; extern const Internal::SimdImpl_DotProduct xDP; extern const Internal::SimdImpl_Round xROUND; - + extern const Internal::SimdImpl_PMove xPMOVSX; extern const Internal::SimdImpl_PMove xPMOVZX; diff --git a/common/src/x86emitter/x86emitter.cpp b/common/src/x86emitter/x86emitter.cpp index 5daba6e590..a3527125ce 100644 --- a/common/src/x86emitter/x86emitter.cpp +++ b/common/src/x86emitter/x86emitter.cpp @@ -729,6 +729,7 @@ __forceinline void xPOPFD() { xWrite8( 0x9D ); } ////////////////////////////////////////////////////////////////////////////////////////// // +__forceinline void xLEAVE() { xWrite8( 0xC9 ); } __forceinline void xRET() { xWrite8( 0xC3 ); } __forceinline void xCBW() { xWrite16( 0x9866 ); } __forceinline void xCWD() { xWrite8( 0x98 ); } diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index da9d5317f5..74d7aaf668 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -328,6 +328,7 @@ static DynGenFunc* DispatcherReg = NULL; static DynGenFunc* JITCompile = NULL; static DynGenFunc* JITCompileInBlock = NULL; static DynGenFunc* EnterRecompiledCode = NULL; +static DynGenFunc* ExitRecompiledCode = NULL; // parameters: // espORebp - 0 for ESP, or 1 for EBP. @@ -427,41 +428,45 @@ static DynGenFunc* _DynGen_EnterRecompiledCode() // use for supplying parameters to cdecl functions. xPUSH( ebp ); - xPUSH( edi ); - xPUSH( esi ); - xPUSH( ebx ); - xMOV( ebp, esp ); + xAND( esp, -0x10 ); - xSUB( esp, 0x10 ); - xMOV( &s_store_ebp, ebp ); + // First 0x10 is for esi, edi, etc. Second 0x10 is for the return address and ebp. The + // third second 0x10 is for C-style CDECL calls we might make from the recompiler + // (parameters for those calls can be stored there!) + + xSUB( esp, 0x30 ); + + xMOV( ptr[ebp-12], edi ); + xMOV( ptr[ebp-8], esi ); + xMOV( ptr[ebp-4], ebx ); + + // Simulate a CALL function by pushing the call address and EBP onto the stack. + xMOV( ptr32[esp+0x10+12], 0xffeeff ); + uptr& imm = *(uptr*)(xGetPtr()-4); + xMOV( ptr32[esp+0x10+8], ebp ); + xMOV( &s_store_esp, esp ); - xSUB( ptr32[&s_store_esp], 4 ); // account for the address pushed when we xCALL + xMOV( &s_store_ebp, ebp ); - //xPUSH( edi ); - //xPUSH( esi ); - //xPUSH( ebx ); + xJMP( ptr32[&DispatcherReg] ); + imm = (uptr)xGetPtr(); + ExitRecompiledCode = (DynGenFunc*)xGetPtr(); - xCALL( ptr32[&DispatcherReg] ); + xLEAVE(); + //xMOV( esp, ebp ); + //xPOP( ebp ); - //xPOP( ebx ); - //xPOP( esi ); - //xPOP( edi ); + //_DynGen_StackFrameCheck(); + + xMOV( edi, ptr[ebp-12] ); + xMOV( esi, ptr[ebp-8] ); + xMOV( ebx, ptr[ebp-4] ); //xMOV( esp, ebp ); //xPOP( ebp ); - //xRET(); - - xADD( ptr32[&s_store_esp], 4 ); // account for the address pushed when we xCALL - _DynGen_StackFrameCheck(); - - xMOV( esp, ebp ); - - xPOP( ebx ); - xPOP( esi ); - xPOP( edi ); - xPOP( ebp ); + xLEAVE(); xRET(); return (DynGenFunc*)retval; @@ -808,18 +813,16 @@ void recClear(u32 addr, u32 size) upperextent = min(upperextent, ceiling); -#ifdef PCSX2_DEVBUILD for (int i = 0; pexblock = recBlocks[i]; i++) { if (s_pCurBlock == PC_GETBLOCK(pexblock->startpc)) continue; u32 blockend = pexblock->startpc + pexblock->size * 4; if (pexblock->startpc >= addr && pexblock->startpc < addr + size * 4 || pexblock->startpc < addr && blockend > addr) { - Console.Error( "Impossible block clearing failure" ); - pxFail( "Impossible block clearing failure" ); + DevCon.Error( "Impossible block clearing failure" ); + pxFailDev( "Impossible block clearing failure" ); } } -#endif if (upperextent > lowerextent) ClearRecLUT(PC_GETBLOCK(lowerextent), (upperextent - lowerextent) / 4); @@ -1284,6 +1287,8 @@ void __fastcall dyna_page_reset(u32 start,u32 sz) // Note: this function is accessed via a JMP, and thus the RET here will exit // recompiled code and take us back to recExecute. + + __asm__ __volatile__( "leave\n jmp %[exitRec]\n" : : [exitRec] "m" (ExitRecompiledCode) : ); } void recRecompile( const u32 startpc )