2009-09-08 12:08:10 +00:00
|
|
|
/* PCSX2 - PS2 Emulator for PCs
|
2010-05-03 14:08:02 +00:00
|
|
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
2009-10-21 02:23:42 +00:00
|
|
|
*
|
2009-09-08 12:08:10 +00:00
|
|
|
* 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.
|
2009-04-19 02:14:50 +00:00
|
|
|
*
|
2009-09-08 12:08:10 +00:00
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
2009-04-19 02:14:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// Implementations found here: CALL and JMP! (unconditional only)
|
2009-11-06 21:45:30 +00:00
|
|
|
|
2016-11-12 15:28:37 +00:00
|
|
|
namespace x86Emitter
|
|
|
|
{
|
2009-04-19 02:14:50 +00:00
|
|
|
|
2016-11-12 15:28:37 +00:00
|
|
|
extern void xJccKnownTarget(JccComparisonType comparison, const void *target, bool slideForward);
|
2009-11-06 21:45:30 +00:00
|
|
|
|
2009-04-19 02:14:50 +00:00
|
|
|
// ------------------------------------------------------------------------
|
2009-11-06 21:45:30 +00:00
|
|
|
struct xImpl_JmpCall
|
2009-04-19 02:14:50 +00:00
|
|
|
{
|
2016-11-12 15:28:37 +00:00
|
|
|
bool isJmp;
|
|
|
|
|
2020-08-19 08:19:28 +00:00
|
|
|
void operator()(const xAddressReg &absreg) const;
|
|
|
|
void operator()(const xIndirectNative &src) const;
|
|
|
|
#ifdef __M_X86_64
|
|
|
|
[[deprecated]] // Should move to xIndirectNative
|
|
|
|
void operator()(const xIndirect32 &absreg) const;
|
|
|
|
#endif
|
2016-11-12 15:28:37 +00:00
|
|
|
|
|
|
|
// Special form for calling functions. This form automatically resolves the
|
|
|
|
// correct displacement based on the size of the instruction being generated.
|
|
|
|
void operator()(void *func) const
|
|
|
|
{
|
|
|
|
if (isJmp)
|
|
|
|
xJccKnownTarget(Jcc_Unconditional, (void *)(uptr)func, false); // double cast to/from (uptr) needed to appease GCC
|
|
|
|
else {
|
|
|
|
// calls are relative to the instruction after this one, and length is
|
|
|
|
// always 5 bytes (16 bit calls are bad mojo, so no bother to do special logic).
|
|
|
|
|
|
|
|
sptr dest = (sptr)func - ((sptr)xGetPtr() + 5);
|
2020-08-19 08:19:28 +00:00
|
|
|
pxAssertMsg(dest == (s32)dest, "Indirect jump is too far, must use a register!");
|
2016-11-12 15:28:37 +00:00
|
|
|
xWrite8(0xe8);
|
|
|
|
xWrite32(dest);
|
|
|
|
}
|
|
|
|
}
|
2009-04-19 02:14:50 +00:00
|
|
|
};
|
2009-04-24 11:25:10 +00:00
|
|
|
|
2015-12-03 19:15:52 +00:00
|
|
|
// yes it is awful. Due to template code is in a header with a nice circular dep.
|
2016-11-12 15:28:37 +00:00
|
|
|
extern const xImpl_Mov xMOV;
|
|
|
|
extern const xImpl_JmpCall xCALL;
|
2015-12-03 19:15:52 +00:00
|
|
|
|
|
|
|
struct xImpl_FastCall
|
|
|
|
{
|
2016-11-12 15:28:37 +00:00
|
|
|
// FIXME: current 64 bits is mostly a copy/past potentially it would require to push/pop
|
|
|
|
// some registers. But I think it is enough to handle the first call.
|
2015-12-03 19:15:52 +00:00
|
|
|
|
2020-08-19 08:19:28 +00:00
|
|
|
void operator()(void *f, const xRegister32 &a1 = xEmptyReg, const xRegister32 &a2 = xEmptyReg) const;
|
2015-12-03 19:15:52 +00:00
|
|
|
|
2020-08-19 08:19:28 +00:00
|
|
|
void operator()(void *f, u32 a1, const xRegister32 &a2) const;
|
|
|
|
void operator()(void *f, const xIndirect32 &a1) const;
|
|
|
|
void operator()(void *f, u32 a1, u32 a2) const;
|
2015-12-03 19:15:52 +00:00
|
|
|
|
2019-06-19 05:08:43 +00:00
|
|
|
#ifdef __M_X86_64
|
2020-08-19 08:19:28 +00:00
|
|
|
void operator()(void *f, const xRegisterLong &a1, const xRegisterLong &a2 = xEmptyReg) const;
|
|
|
|
void operator()(void *f, u32 a1, const xRegisterLong &a2) const;
|
|
|
|
[[deprecated]] // Switch to xIndirect32, as the size of this isn't obvious
|
2015-12-03 19:15:52 +00:00
|
|
|
#endif
|
2020-08-19 08:19:28 +00:00
|
|
|
void operator()(void *f, const xIndirectVoid &a1) const;
|
2015-12-03 19:15:52 +00:00
|
|
|
|
2016-11-12 15:28:37 +00:00
|
|
|
template <typename T>
|
2020-08-19 08:19:28 +00:00
|
|
|
__fi void operator()(T *func, u32 a1, const xRegisterLong &a2 = xEmptyReg) const
|
2016-11-12 15:28:37 +00:00
|
|
|
{
|
2020-08-19 08:19:28 +00:00
|
|
|
(*this)((void *)func, a1, a2);
|
2016-11-12 15:28:37 +00:00
|
|
|
}
|
2015-12-03 19:15:52 +00:00
|
|
|
|
2016-11-12 15:28:37 +00:00
|
|
|
template <typename T>
|
2020-08-19 08:19:28 +00:00
|
|
|
__fi void operator()(T *func, const xIndirect32 &a1) const
|
2016-11-12 15:28:37 +00:00
|
|
|
{
|
2020-08-19 08:19:28 +00:00
|
|
|
(*this)((void*)func, a1);
|
2016-11-12 15:28:37 +00:00
|
|
|
}
|
2015-12-03 19:15:52 +00:00
|
|
|
|
2016-11-12 15:28:37 +00:00
|
|
|
template <typename T>
|
|
|
|
__fi void operator()(T *func, u32 a1, u32 a2) const
|
|
|
|
{
|
2020-08-19 08:19:28 +00:00
|
|
|
(*this)((void*)func, a1, a2);
|
2016-11-12 15:28:37 +00:00
|
|
|
}
|
2015-12-03 19:15:52 +00:00
|
|
|
|
2019-06-19 05:08:43 +00:00
|
|
|
#ifdef __M_X86_64
|
2020-08-19 08:19:28 +00:00
|
|
|
[[deprecated]] // Switch to xIndirectNative
|
|
|
|
void operator()(const xIndirect32 &f, const xRegisterLong &a1 = xEmptyReg, const xRegisterLong &a2 = xEmptyReg) const;
|
2015-12-03 19:15:52 +00:00
|
|
|
#endif
|
|
|
|
|
2020-08-19 08:19:28 +00:00
|
|
|
void operator()(const xIndirectNative &f, const xRegisterLong &a1 = xEmptyReg, const xRegisterLong &a2 = xEmptyReg) const;
|
2015-12-03 19:15:52 +00:00
|
|
|
};
|
|
|
|
|
2016-11-12 15:28:37 +00:00
|
|
|
} // End namespace x86Emitter
|