/* PCSX2 - PS2 Emulator for PCs * Copyright (C) 2002-2010 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. * * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with PCSX2. * If not, see . */ /* * ix86 core v0.9.1 * * Original Authors (v0.6.2 and prior): * linuzappz * alexey silinov * goldfinger * zerofrog(@gmail.com) * * Authors of v0.9.1: * Jake.Stine(@gmail.com) * cottonvibes(@gmail.com) * sudonim(1@gmail.com) */ #include "tests/emitter/reference/internal.h" namespace x86Emitter { void xImpl_JmpCall::operator()(const xAddressReg& absreg) const { // Jumps are always wide and don't need the rex.W xOpWrite(0, 0xff, isJmp ? 4 : 2, absreg.GetNonWide()); } void xImpl_JmpCall::operator()(const xIndirectNative& src) const { // Jumps are always wide and don't need the rex.W EmitRex(0, xIndirect32(src.Base, src.Index, 1, 0)); xWrite8(0xff); EmitSibMagic(isJmp ? 4 : 2, src); } #ifndef PCSX2_C89_EMITTER const xImpl_JmpCall xJMP = {true}; #endif #ifndef PCSX2_C89_EMITTER const xImpl_JmpCall xCALL = {false}; #endif template void prepareRegsForFastcall(const Reg1& a1, const Reg2& a2) { if (a1.IsEmpty()) return; // Make sure we don't mess up if someone tries to fastcall with a1 in arg2reg and a2 in arg1reg if (a2.Id != arg1reg.Id) { xMOV(Reg1(arg1reg), a1); if (!a2.IsEmpty()) { xMOV(Reg2(arg2reg), a2); } } else if (a1.Id != arg2reg.Id) { xMOV(Reg2(arg2reg), a2); xMOV(Reg1(arg1reg), a1); } else { xPUSH(a1); xMOV(Reg2(arg2reg), a2); xPOP(Reg1(arg1reg)); } } void xImpl_FastCall::operator()(const void* f, const xRegister32& a1, const xRegister32& a2) const { prepareRegsForFastcall(a1, a2); uptr disp = ((uptr)x86Ptr + 5) - (uptr)f; if ((sptr)disp == (s32)disp) { xCALL(f); } else { xLEA(rax, ptr64[f]); xCALL(rax); } } void xImpl_FastCall::operator()(const void* f, const xRegisterLong& a1, const xRegisterLong& a2) const { prepareRegsForFastcall(a1, a2); uptr disp = ((uptr)x86Ptr + 5) - (uptr)f; if ((sptr)disp == (s32)disp) { xCALL(f); } else { xLEA(rax, ptr64[f]); xCALL(rax); } } void xImpl_FastCall::operator()(const void* f, u32 a1, const xRegisterLong& a2) const { if (!a2.IsEmpty()) { xMOV(arg2reg, a2); } xMOV(arg1reg, a1); (*this)(f, arg1reg, arg2reg); } void xImpl_FastCall::operator()(const void* f, void* a1) const { xLEA(arg1reg, ptr[a1]); (*this)(f, arg1reg, arg2reg); } void xImpl_FastCall::operator()(const void* f, u32 a1, const xRegister32& a2) const { if (!a2.IsEmpty()) { xMOV(arg2regd, a2); } xMOV(arg1regd, a1); (*this)(f, arg1regd, arg2regd); } void xImpl_FastCall::operator()(const void* f, const xIndirect32& a1) const { xMOV(arg1regd, a1); (*this)(f, arg1regd); } void xImpl_FastCall::operator()(const void* f, u32 a1, u32 a2) const { xMOV(arg1regd, a1); xMOV(arg2regd, a2); (*this)(f, arg1regd, arg2regd); } void xImpl_FastCall::operator()(const xIndirectNative& f, const xRegisterLong& a1, const xRegisterLong& a2) const { prepareRegsForFastcall(a1, a2); xCALL(f); } #ifndef PCSX2_C89_EMITTER const xImpl_FastCall xFastCall = {}; #endif } // namespace x86Emitter