64-bit support for CSGO on Linux and macOS (#705)

This commit is contained in:
Scott Ehlert
2017-12-20 01:56:23 -06:00
committed by GitHub
parent 057a5790e2
commit ce1a4dcac0
90 changed files with 15682 additions and 947 deletions
+24 -21
View File
@@ -1,27 +1,30 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
binary = SM.ExtLibrary(builder, 'bintools.ext')
binary.compiler.defines += ['HOOKING_ENABLED']
binary.compiler.cxxincludes += [
os.path.join(SM.mms_root, 'core', 'sourcehook'),
os.path.join(builder.sourcePath, 'public', 'jit'),
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
]
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
binary.compiler.cxxflags += ['-fno-rtti']
elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-']
for arch in SM.archs:
binary = SM.ExtLibrary(builder, 'bintools.ext', arch)
binary.compiler.defines += ['HOOKING_ENABLED']
binary.compiler.cxxincludes += [
os.path.join(SM.mms_root, 'core', 'sourcehook'),
os.path.join(builder.sourcePath, 'public', 'jit'),
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
]
if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang':
binary.compiler.cxxflags += ['-fno-rtti']
elif binary.compiler.family == 'msvc':
binary.compiler.cxxflags += ['/GR-']
binary.sources += [
'extension.cpp',
'CallMaker.cpp',
'CallWrapper.cpp',
'HookWrapper.cpp',
'jit_call.cpp',
'jit_hook.cpp',
'../../public/smsdk_ext.cpp'
]
binary.sources += [
'extension.cpp',
'CallMaker.cpp',
'CallWrapper.cpp',
'../../public/smsdk_ext.cpp'
]
if arch == 'x64':
binary.sources += ['jit_call_x64.cpp']
else:
binary.sources += ['jit_call.cpp']
SM.extensions += [builder.Add(binary)]
SM.extensions += [builder.Add(binary)]
+57 -4
View File
@@ -82,7 +82,8 @@ ICallWrapper *CallMaker::CreateCall(void *address,
CallConvention cv,
const PassInfo *retInfo,
const PassInfo paramInfo[],
unsigned int numParams)
unsigned int numParams,
unsigned int fnFlags)
{
SourceHook::CProtoInfoBuilder protoInfo(GetSHCallConvention(cv));
@@ -103,7 +104,11 @@ ICallWrapper *CallMaker::CreateCall(void *address,
NULL, NULL, NULL, NULL);
}
#if defined PLATFORM_X64
return g_CallMaker2.CreateCall(address, &(*protoInfo), retInfo, paramInfo, fnFlags);
#else
return g_CallMaker2.CreateCall(address, &(*protoInfo));
#endif
}
ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx,
@@ -111,7 +116,8 @@ ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx,
unsigned int thisOffs,
const PassInfo *retInfo,
const PassInfo paramInfo[],
unsigned int numParams)
unsigned int numParams,
unsigned int fnFlags)
{
SourceHook::MemFuncInfo info;
info.isVirtual = true;
@@ -138,12 +144,16 @@ ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx,
NULL, NULL, NULL, NULL);
}
#if defined PLATFORM_X64
return g_CallMaker2.CreateVirtualCall(&(*protoInfo), &info, retInfo, paramInfo, fnFlags);
#else
return g_CallMaker2.CreateVirtualCall(&(*protoInfo), &info);
#endif
}
ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo)
{
#ifdef PLATFORM_X86
CallWrapper *pWrapper = new CallWrapper(protoInfo);
pWrapper->SetCalleeAddr(address);
@@ -151,11 +161,15 @@ ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo
pWrapper->SetCodeBaseAddr(addr);
return pWrapper;
#else
return nullptr;
#endif
}
ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info)
{
#ifdef PLATFORM_X86
CallWrapper *pWrapper = new CallWrapper(protoInfo);
pWrapper->SetMemFuncInfo(info);
@@ -163,9 +177,48 @@ ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoIn
pWrapper->SetCodeBaseAddr(addr);
return pWrapper;
#else
return nullptr;
#endif
}
#if defined HOOKING_ENABLED
ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo,
const PassInfo *retInfo, const PassInfo paramInfo[],
unsigned int fnFlags)
{
#ifdef PLATFORM_X64
CallWrapper *pWrapper = new CallWrapper(protoInfo, retInfo, paramInfo, fnFlags);
pWrapper->SetCalleeAddr(address);
void *addr = JIT_CallCompile(pWrapper, FuncAddr_Direct);
pWrapper->SetCodeBaseAddr(addr);
return pWrapper;
#else
return nullptr;
#endif
}
ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info,
const PassInfo *retInfo,
const PassInfo paramInfo[],
unsigned int fnFlags)
{
#ifdef PLATFORM_X64
CallWrapper *pWrapper = new CallWrapper(protoInfo, retInfo, paramInfo, fnFlags);
pWrapper->SetMemFuncInfo(info);
void *addr = JIT_CallCompile(pWrapper, FuncAddr_VTable);
pWrapper->SetCodeBaseAddr(addr);
return pWrapper;
#else
return nullptr;
#endif
}
#if 0
IHookWrapper *CallMaker2::CreateVirtualHook(SourceHook::ISourceHook *pSH,
const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info,
+10 -7
View File
@@ -34,7 +34,6 @@
#include "CallWrapper.h"
#include "HookWrapper.h"
using namespace SourceMod;
@@ -45,26 +44,30 @@ public: //IBinTools
CallConvention cv,
const PassInfo *retInfo,
const PassInfo paramInfo[],
unsigned int numParams);
unsigned int numParams,
unsigned int fnFlags);
ICallWrapper *CreateVCall(unsigned int vtblIdx,
unsigned int vtblOffs,
unsigned int thisOffs,
const PassInfo *retInfo,
const PassInfo paramInfo[],
unsigned int numParams);
unsigned int numParams,
unsigned int fnFlags);
};
class CallMaker2
#if defined HOOKING_ENABLED
: public IBinTools2
#endif
{
public: //IBinTools2
virtual ICallWrapper *CreateCall(void *address,
const SourceHook::ProtoInfo *protoInfo);
virtual ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info);
#if defined HOOKING_ENABLED
ICallWrapper *CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo,
const PassInfo *retInfo, const PassInfo paramInfo[], unsigned int fnFlags);
ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info, const PassInfo *retInfo,
const PassInfo paramInfo[], unsigned int fnFlags);
#if 0
virtual IHookWrapper *CreateVirtualHook(SourceHook::ISourceHook *pSH,
const SourceHook::ProtoInfo *protoInfo,
const SourceHook::MemFuncInfo *info,
+22 -1
View File
@@ -33,7 +33,7 @@
#include "CallWrapper.h"
#include "CallMaker.h"
CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo)
CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo) : m_FnFlags(0)
{
m_AddrCodeBase = NULL;
m_AddrCallee = NULL;
@@ -77,6 +77,22 @@ CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo)
}
}
CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo, const PassInfo *retInfo,
const PassInfo paramInfo[], unsigned int fnFlags) : CallWrapper(protoInfo)
{
m_RetParam->fields = retInfo->fields;
m_RetParam->numFields = retInfo->numFields;
unsigned int argnum = protoInfo->numOfParams;
for (unsigned int i = 0; i < argnum; i++)
{
m_Params[i].info.fields = paramInfo[i].fields;
m_Params[i].info.numFields = paramInfo[i].numFields;
}
m_FnFlags = fnFlags;
}
CallWrapper::~CallWrapper()
{
delete [] m_Params;
@@ -184,3 +200,8 @@ unsigned int CallWrapper::GetParamOffset(unsigned int num)
return m_Params[num].offset;
}
unsigned int CallWrapper::GetFunctionFlags()
{
return m_FnFlags;
}
+4
View File
@@ -47,6 +47,8 @@ class CallWrapper : public ICallWrapper
{
public:
CallWrapper(const SourceHook::ProtoInfo *protoInfo);
CallWrapper(const SourceHook::ProtoInfo *protoInfo, const PassInfo *retInfo,
const PassInfo paramInfo[], unsigned int fnFlags);
~CallWrapper();
public: //ICallWrapper
CallConvention GetCallConvention();
@@ -59,6 +61,7 @@ public: //ICallWrapper
SourceHook::ProtoInfo::CallConvention GetSHCallConvention();
const SourceHook::PassInfo *GetSHParamInfo(unsigned int num);
unsigned int GetParamOffset(unsigned int num);
unsigned int GetFunctionFlags();
public:
void SetCalleeAddr(void *addr);
void SetCodeBaseAddr(void *addr);
@@ -74,6 +77,7 @@ private:
void *m_AddrCallee;
void *m_AddrCodeBase;
SourceHook::MemFuncInfo m_FuncInfo;
unsigned int m_FnFlags;
};
#endif //_INCLUDE_SOURCEMOD_CALLWRAPPER_H_
-6
View File
@@ -50,12 +50,6 @@ bool BinTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
g_SPEngine = g_pSM->GetScriptingEngine();
g_pShareSys->AddInterface(myself, &g_CallMaker);
/* IBinTools2 is only compatible with SH v5 */
if (g_pSM->GetShApiVersion() >= 5)
{
g_pShareSys->AddInterface(myself, &g_CallMaker2);
}
return true;
}
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -34,11 +34,12 @@
#include <jit_helpers.h>
#include <x86_macros.h>
#include <sm_platform.h>
#include "CallWrapper.h"
#include "HookWrapper.h"
void *JIT_CallCompile(CallWrapper *pWrapper, FuncAddrMethod method);
#if defined HOOKING_ENABLED
#if 0
void *JIT_HookCompile(HookWrapper *pWrapper);
void JIT_FreeHook(void *addr);
#endif
+1 -1
View File
@@ -214,7 +214,7 @@ inline void Write_Push_Params(JitWriter *jit,
IA32_Push_Reg(jit, kREG_EBX);
//push <pWrapper>
IA32_Push_Imm32(jit, (jit_int32_t)pWrapper);
IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)pWrapper);
}
inline void Write_Call_Handler(JitWriter *jit, void *addr)
+656
View File
@@ -0,0 +1,656 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod BinTools Extension
* Copyright (C) 2004-2017 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program 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
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*/
#include <jit_helpers.h>
#include <x86_macros.h>
// 64-bit registers
const jit_uint8_t kREG_RAX = kREG_EAX;
const jit_uint8_t kREG_RCX = kREG_ECX;
const jit_uint8_t kREG_RDX = kREG_EDX;
const jit_uint8_t kREG_RBX = kREG_EBX;
const jit_uint8_t kREG_RSP = kREG_ESP;
const jit_uint8_t kREG_RBP = kREG_EBP;
const jit_uint8_t kREG_RSI = kREG_ESI;
const jit_uint8_t kREG_RDI = kREG_EDI;
const jit_uint8_t kREG_R8 = 8;
const jit_uint8_t kREG_R9 = 9;
const jit_uint8_t kREG_R10 = 10;
const jit_uint8_t kREG_R11 = 11;
const jit_uint8_t kREG_R12 = 12;
const jit_uint8_t kREG_R13 = 13;
const jit_uint8_t kREG_R14 = 14;
const jit_uint8_t kREG_R15 = 15;
const jit_uint8_t kREG_XMM0 = 0;
const jit_uint8_t kREG_XMM1 = 1;
const jit_uint8_t kREG_XMM2 = 2;
const jit_uint8_t kREG_XMM3 = 3;
const jit_uint8_t kREG_XMM4 = 4;
const jit_uint8_t kREG_XMM5 = 5;
const jit_uint8_t kREG_XMM6 = 6;
const jit_uint8_t kREG_XMM7 = 7;
const jit_uint8_t kREG_XMM8 = 8;
const jit_uint8_t kREG_XMM9 = 9;
const jit_uint8_t kREG_XMM10 = 10;
const jit_uint8_t kREG_XMM11 = 11;
const jit_uint8_t kREG_XMM12 = 12;
const jit_uint8_t kREG_XMM13 = 13;
const jit_uint8_t kREG_XMM14 = 14;
const jit_uint8_t kREG_XMM15 = 15;
#define X64_REX_PREFIX 0x40
#define IA32_MOV_REG8_IMM8 0xB0
inline jit_uint8_t x64_rex(bool w, jit_uint8_t r, jit_uint8_t x, jit_uint8_t b)
{
return (X64_REX_PREFIX | ((jit_uint8_t)w << 3) | ((r>>3) << 2) | ((x>>3) << 1) | (b >> 3));
}
inline void X64_Push_Reg(JitWriter *jit, jit_uint8_t reg)
{
if (reg >= kREG_R8)
jit->write_ubyte(x64_rex(false, 0, 0, reg));
IA32_Push_Reg(jit, reg & 7);
}
inline void X64_Mov_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Mov_Reg_Rm(jit, dest & 7, src & 7, mode);
}
inline void X64_Mov_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Mov_Reg_Rm_Disp8(jit, dest & 7, src & 7, disp);
}
inline void X64_Mov_Reg_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Mov_Reg_Rm_Disp32(jit, dest & 7, src & 7, disp);
}
inline void X64_Mov_Reg32_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
if (src>= kREG_R8 || dest >= kREG_R8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
IA32_Mov_Reg_Rm(jit, dest & 7, src & 7, mode);
}
inline void X64_Mov_Reg32_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (src>= kREG_R8 || dest >= kREG_R8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
IA32_Mov_Reg_Rm_Disp8(jit, dest & 7, src & 7, disp);
}
inline void X64_Mov_Reg32_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (src>= kREG_R8 || dest >= kREG_R8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
IA32_Mov_Reg_Rm_Disp32(jit, dest & 7, src & 7, disp);
}
inline void X64_And_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value)
{
jit->write_ubyte(x64_rex(true, 0, 0, reg));
IA32_And_Rm_Imm8(jit, reg & 7, mode, value);
}
inline void X64_Sub_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t val, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, 5, 0, reg));
IA32_Sub_Rm_Imm8(jit, reg & 7, val, mode);
}
inline void X64_Sub_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t val, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, 5, 0, reg));
IA32_Sub_Rm_Imm32(jit, reg & 7, val, mode);
}
inline void X64_Pop_Reg(JitWriter *jit, jit_uint8_t reg)
{
if (reg >= kREG_R8)
jit->write_ubyte(x64_rex(false, 0, 0, reg));
IA32_Pop_Reg(jit, reg & 7);
}
inline void X64_Return(JitWriter *jit)
{
IA32_Return(jit);
}
inline void X64_Movzx_Reg64_Rm8_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm8_Disp8(jit, dest & 7, src & 7, disp);
}
inline void X64_Movzx_Reg64_Rm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm8(jit, dest & 7, src & 7, mode);
}
inline void X64_Movzx_Reg64_Rm8_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm8_Disp32(jit, dest & 7, src & 7, disp);
}
inline void X64_Mov_RmRSP_Reg(JitWriter *jit, jit_uint8_t src)
{
jit->write_ubyte(x64_rex(true, kREG_RSP, 0, src));
jit->write_ubyte(IA32_MOV_RM_REG);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, kREG_RSP));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, kREG_RSP));
}
inline void X64_Mov_RmRSP_Disp8_Reg(JitWriter *jit, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, src, 0, kREG_RSP));
jit->write_ubyte(IA32_MOV_RM_REG);
jit->write_ubyte(ia32_modrm(MOD_DISP8, src & 7, kREG_RSP));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, kREG_RSP));
jit->write_byte(disp);
}
inline void X64_Mov_RmRSP_Disp32_Reg(JitWriter *jit, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, src, 0, kREG_RSP));
jit->write_ubyte(IA32_MOV_RM_REG);
jit->write_ubyte(ia32_modrm(MOD_DISP32, src & 7, kREG_RSP));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, kREG_RSP));
jit->write_byte(disp);
}
inline void X64_Movzx_Reg64_Rm16(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm16(jit, dest & 7, src & 7, mode);
}
inline void X64_Movzx_Reg64_Rm16_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm16_Disp8(jit, dest & 7, src & 7, disp);
}
inline void X64_Movzx_Reg64_Rm16_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
jit->write_ubyte(x64_rex(true, dest, 0, src));
IA32_Movzx_Reg32_Rm16_Disp32(jit, dest & 7, src & 7, disp);
}
inline void X64_Lea_DispRegImm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int8_t val)
{
jit->write_ubyte(x64_rex(true, dest, 0, src_base));
IA32_Lea_DispRegImm8(jit, dest & 7, src_base & 7, val);
}
inline void X64_Lea_DispRegImm32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int32_t val)
{
jit->write_ubyte(x64_rex(true, dest, 0, src_base));
IA32_Lea_DispRegImm32(jit, dest & 7, src_base & 7, val);
}
inline void X64_Add_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t value, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, 0, 0, reg));
IA32_Add_Rm_Imm8(jit, reg & 7, value, mode);
}
inline void X64_Add_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t value, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, 0, 0, reg));
IA32_Add_Rm_Imm32(jit, reg & 7, value, mode);
}
inline void X64_Movaps_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movups_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movaps_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x29);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, dest & 7));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
}
inline void X64_Movapd_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
jit->write_ubyte(0x66);
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x29);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, dest & 7));
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
}
inline void X64_Movups_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, dest & 7));
}
inline void X64_Movupd_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
jit->write_ubyte(0x66);
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src & 7, dest & 7));
}
inline void X64_Movupd_Rm_Disp8_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(0x66);
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_DISP8, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movaps_Rm_Disp8_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x29);
jit->write_ubyte(ia32_modrm(MOD_DISP8, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movups_Rm_Disp8_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_DISP8, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movaps_Rm_Disp32_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x29);
jit->write_ubyte(ia32_modrm(MOD_DISP32, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movups_Rm_Disp32_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x11);
jit->write_ubyte(ia32_modrm(MOD_DISP32, src & 7, dest & 7));
jit->write_byte(disp);
}
inline void X64_Movlps_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x12);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movhps_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x16);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movaps_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movups_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movlps_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x12);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movhps_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x16);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movaps_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movups_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movapd_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movupd_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest & 7, src & 7));
}
inline void X64_Movapd_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movupd_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_DISP8, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movapd_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x28);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Movupd_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp)
{
if (dest >= kREG_XMM8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, dest, 0, src));
jit->write_ubyte(0x66);
jit->write_ubyte(0x0F);
jit->write_ubyte(0x10);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, src & 7));
jit->write_byte(disp);
}
inline void X64_Cld(JitWriter *jit)
{
IA32_Cld(jit);
}
inline void X64_Rep(JitWriter *jit)
{
IA32_Rep(jit);
}
inline void X64_Movsq(JitWriter *jit)
{
jit->write_ubyte(x64_rex(true, 0, 0, 0));
jit->write_ubyte(IA32_MOVSD);
}
inline void X64_Movsb(JitWriter *jit)
{
jit->write_ubyte(IA32_MOVSB);
}
inline void X64_Lea_Reg_DispRegMultImm8(JitWriter *jit,
jit_uint8_t dest,
jit_uint8_t src_base,
jit_uint8_t src_index,
jit_uint8_t scale,
jit_int8_t val)
{
jit->write_ubyte(x64_rex(true, dest, 0, src_index));
IA32_Lea_Reg_DispRegMultImm8(jit, dest & 7, src_base, src_index & 7, scale, val);
}
inline void X64_Lea_Reg_DispRegMultImm32(JitWriter *jit,
jit_uint8_t dest,
jit_uint8_t src_base,
jit_uint8_t src_index,
jit_uint8_t scale,
jit_int32_t val)
{
jit->write_ubyte(x64_rex(true, dest, 0, src_index));
jit->write_ubyte(IA32_LEA_REG_MEM);
jit->write_ubyte(ia32_modrm(MOD_DISP32, dest & 7, kREG_SIB));
jit->write_ubyte(ia32_sib(scale, src_index & 7, src_base));
jit->write_int32(val);
}
inline jitoffs_t X64_Mov_Reg_Imm32(JitWriter *jit, jit_uint8_t dest, jit_int32_t num)
{
jitoffs_t offs;
jit->write_ubyte(x64_rex(true, 0, 0, dest));
jit->write_ubyte(0xC7);
jit->write_ubyte(ia32_modrm(MOD_REG, 0, dest & 7));
offs = jit->get_outputpos();
jit->write_int32(num);
return offs;
}
inline jitoffs_t X64_Mov_Reg_Imm64(JitWriter *jit, jit_uint8_t dest, jit_int64_t num)
{
jitoffs_t offs;
jit->write_ubyte(x64_rex(true, 0, 0, dest));
jit->write_ubyte(IA32_MOV_REG_IMM+(dest & 7));
offs = jit->get_outputpos();
jit->write_int64(num);
return offs;
}
inline void X64_Mov_Rm8_Reg8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
if (dest >= kREG_R8 || src > kREG_R8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(IA32_MOV_RM8_REG8);
if ((dest & 7) == kREG_RBP) // Using rbp/r13 requires a displacement
mode = MOD_DISP8;
jit->write_ubyte(ia32_modrm(mode, src & 7, dest & 7));
if ((dest & 7) == kREG_RSP) // rsp/r12 needs SIB byte
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
else if ((dest & 7) == kREG_RBP)
jit->write_ubyte(0); // Displacement of 0 needed to use rbp/r13
}
inline void X64_Mov_Rm32_Reg32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
if (dest >= kREG_R8 || src > kREG_R8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(IA32_MOV_RM_REG);
if ((dest & 7) == kREG_RBP) // Using rbp/r13 requires a displacement
mode = MOD_DISP8;
jit->write_ubyte(ia32_modrm(mode, src & 7, dest & 7));
if ((dest & 7) == kREG_RSP) // rsp/r12 needs SIB byte
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
else if ((dest & 7) == kREG_RBP)
jit->write_ubyte(0); // Displacement of 0 needed to use rbp/r13
}
inline void X64_Mov_Rm16_Reg16(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(IA32_16BIT_PREFIX);
X64_Mov_Rm32_Reg32(jit, dest, src, mode);
}
inline void X64_Mov_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode)
{
jit->write_ubyte(x64_rex(true, src, 0, dest));
jit->write_ubyte(IA32_MOV_RM_REG);
if ((dest & 7) == kREG_RBP) // Using rbp/r13 requires a displacement
mode = MOD_DISP8;
jit->write_ubyte(ia32_modrm(mode, src & 7, dest & 7));
if ((dest & 7) == kREG_RSP) // rsp/r12 needs SIB byte
jit->write_ubyte(ia32_sib(NOSCALE, kREG_NOIDX, dest & 7));
else if ((dest & 7) == kREG_RBP)
jit->write_ubyte(0); // Displacement of 0 needed to use rbp/r13
}
inline void X64_Mov_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp)
{
jit->write_ubyte(x64_rex(true, src, 0, dest));
IA32_Mov_Rm_Reg_Disp8(jit, dest & 7, src & 7, disp);
}
inline jitoffs_t X64_Call_Imm32(JitWriter *jit, jit_int32_t disp)
{
return IA32_Call_Imm32(jit, disp);
}
inline void X64_Write_Jump32_Abs(JitWriter *jit, jitoffs_t jmp, void *target)
{
IA32_Write_Jump32_Abs(jit, jmp, target);
}
inline void X64_Call_Reg(JitWriter *jit, jit_uint8_t reg)
{
if (reg >= kREG_R8)
jit->write_ubyte(x64_rex(false, 0, 0, reg));
IA32_Call_Reg(jit, reg & 7);
}
inline jitoffs_t X64_Mov_Reg8_Imm8(JitWriter *jit, jit_uint8_t dest, jit_int8_t value)
{
jitoffs_t offs;
if (dest >= kREG_R8)
jit->write_ubyte(x64_rex(false, 0, 0, dest));
jit->write_ubyte(IA32_MOV_REG8_IMM8+(dest & 7));
offs = jit->get_outputpos();
jit->write_byte(value);
return offs;
}
inline void X64_Movd_Reg32_Xmm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
jit->write_ubyte(0x66);
if (dest >= kREG_R8 || src >= kREG_XMM8)
jit->write_ubyte(x64_rex(false, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x7E);
jit->write_ubyte(ia32_modrm(MOD_REG, src & 7, dest & 7));
}
inline void X64_Movq_Reg_Xmm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src)
{
jit->write_ubyte(0x66);
jit->write_ubyte(x64_rex(true, src, 0, dest));
jit->write_ubyte(0x0F);
jit->write_ubyte(0x7E);
jit->write_ubyte(ia32_modrm(MOD_REG, src & 7, dest & 7));
}