Navigation Menu

Skip to content

Commit

Permalink
Add float return type support (lol :D)
Browse files Browse the repository at this point in the history
  • Loading branch information
theAsmodai committed Jan 26, 2018
1 parent 76f64ff commit 80555d3
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 23 deletions.
42 changes: 34 additions & 8 deletions metamod/src/callback_jit.cpp
Expand Up @@ -69,7 +69,7 @@ void CForwardCallbackJIT::naked_main()
};

auto globals = ebx;
auto locals_size = m_jitdata->has_ret ? sizeof(int) * 2 /* orig + over */ : 0;
auto locals_size = m_jitdata->rettype != rt_void ? sizeof(int) * 2 /* orig + over */ : 0;
auto framesize = align(locals_size + sizeof(meta_globals_t) + /* for align */m_jitdata->args_count * sizeof(int), xmmreg_size) - m_jitdata->args_count * sizeof(int);

if (m_jitdata->has_varargs) {
Expand Down Expand Up @@ -115,7 +115,7 @@ void CForwardCallbackJIT::naked_main()
mov(dword_ptr[globals + mg_esp_save], esp);

// setup retval pointers
if (m_jitdata->has_ret) {
if (m_jitdata->rettype != rt_void) {
lea(eax, dword_ptr[esp + over_ret]);
mov(dword_ptr[globals + mg_orig_ret], esp);
mov(dword_ptr[globals + mg_over_ret], eax);
Expand Down Expand Up @@ -160,7 +160,13 @@ void CForwardCallbackJIT::naked_main()
mov(dword_ptr[globals + mg_status], ecx);

// save return value if override or supercede
if (m_jitdata->has_ret) {
if (m_jitdata->rettype != rt_void) {
if (m_jitdata->rettype == rt_float) {
sub(esp, sizeof(int));
fstp(dword_ptr[esp]);
pop(eax);
}

mov(ecx, dword_ptr[esp + over_ret]);
cmp(edx, MRES_OVERRIDE);
cmovae(ecx, eax);
Expand All @@ -181,18 +187,26 @@ void CForwardCallbackJIT::naked_main()
}

// store original return value
if (m_jitdata->has_ret) {
if (m_jitdata->rettype == rt_integer) {
if (m_jitdata->pfn_original)
mov(dword_ptr[esp + orig_ret], eax);
else
mov(dword_ptr[esp + orig_ret], TRUE); // fix for should collide :/

jmp("skip_supercede");
}
else if (m_jitdata->rettype == rt_float) {
if (m_jitdata->pfn_original)
fstp(dword_ptr[esp + orig_ret]);
else
mov(dword_ptr[esp + orig_ret], 0);

jmp("skip_supercede");
}
}
L("skip_original");
{
if (m_jitdata->has_ret) {
if (m_jitdata->rettype != rt_void) {
// if supercede
mov(eax, dword_ptr[esp + over_ret]);
mov(dword_ptr[esp + orig_ret], eax);
Expand Down Expand Up @@ -241,7 +255,13 @@ void CForwardCallbackJIT::naked_main()
mov(dword_ptr[globals + mg_status], ecx);

// save return value if override or supercede
if (m_jitdata->has_ret) {
if (m_jitdata->rettype != rt_void) {
if (m_jitdata->rettype == rt_float) {
sub(esp, sizeof(int));
fstp(dword_ptr[esp]);
pop(eax);
}

cmp(edx, MRES_OVERRIDE);
mov(ecx, dword_ptr[esp + over_ret]);
cmovae(ecx, eax);
Expand All @@ -264,11 +284,17 @@ void CForwardCallbackJIT::naked_main()
movq(qword_ptr[globals + xmmreg_size], xmm1);

// setup return value and override it if needed
if (m_jitdata->has_ret) {
if (m_jitdata->rettype == rt_integer) {
mov(eax, dword_ptr[esp + orig_ret]);
cmp(dword_ptr[globals + mg_status], MRES_OVERRIDE);
cmovae(eax, dword_ptr[esp + over_ret]);
}
else if (m_jitdata->rettype == rt_float) {
lea(eax, dword_ptr[esp + over_ret]);
cmp(dword_ptr[globals + mg_status], MRES_OVERRIDE);
cmovb(eax, esp); // orig_ret
fld(dword_ptr[eax]);
}

// epilogue
mov(esp, ebp);
Expand All @@ -280,7 +306,7 @@ void CForwardCallbackJIT::naked_main()
void CForwardCallbackJIT::call_func(Reg32 addr)
{
const size_t fixed_args_count = m_jitdata->args_count - (m_jitdata->has_varargs ? 1u /* excluding format string */ : 0u);
const size_t strbuf_offset = m_jitdata->has_ret ? sizeof(int) * 2u /* orig + over */ : 0u;
const size_t strbuf_offset = m_jitdata->rettype != rt_void ? sizeof(int) * 2u /* orig + over */ : 0u;

// push formatted buf instead of format string
if (m_jitdata->has_varargs) {
Expand Down
43 changes: 31 additions & 12 deletions metamod/src/callback_jit.h
@@ -1,13 +1,20 @@
#pragma once

#define CDATA_ENTRY(s, x, p, h) {#x, offsetof(s, x), (uint8)getArgsCount(decltype(s##::##x)()), !is_void(decltype(s##::##x)()), is_varargs(decltype(s##::##x)()), p, h}
#define CDATA_ENTRY(s, x, p, h) {#x, offsetof(s, x), (uint8)getArgsCount(decltype(s##::##x)()), getRetType(decltype(s##::##x)()), is_varargs(decltype(s##::##x)()), p, h}

enum rettype_t : uint8_t
{
rt_void,
rt_integer,
rt_float
};

struct jitdata_t
{
size_t pfn_original;
size_t pfn_offset; // from fn table
uint8 args_count;
bool has_ret;
rettype_t rettype;
bool has_varargs;
uint8 mm_hook_time;
size_t mm_hook;
Expand All @@ -26,7 +33,7 @@ struct compile_data_t
const char* name;
size_t offset;
uint8 args_count;
bool has_ret;
rettype_t rettype;
bool has_varargs;
uint8 mm_hook_time;
size_t mm_hook;
Expand All @@ -45,27 +52,39 @@ size_t getArgsCount(ret_t (*)(t_args..., ...))
}

template<typename ...t_args>
bool is_void(void (*)(t_args...))
rettype_t getRetType(void (*)(t_args..., ...))
{
return true;
return rt_void;
}

template<typename ...t_args>
bool is_void(void (*)(t_args..., ...))
rettype_t getRetType(void(*)(t_args...))
{
return true;
return rt_void;
}

template<typename ret_t, typename ...t_args>
bool is_void(ret_t (*)(t_args..., ...))
template<typename ...t_args>
rettype_t getRetType(float (*)(t_args...))
{
return false;
return rt_float;
}

template<typename ...t_args>
rettype_t getRetType(double (*)(t_args...))
{
return rt_float;
}

template<typename ...t_args>
rettype_t getRetType(long double (*)(t_args...))
{
return rt_float;
}

template<typename ret_t, typename ...t_args>
bool is_void(ret_t (*)(t_args...))
rettype_t getRetType(ret_t (*)(t_args...))
{
return false;
return rt_integer;
}

template<typename ret_t, typename ...t_args>
Expand Down
4 changes: 2 additions & 2 deletions metamod/src/dllapi.cpp
Expand Up @@ -227,7 +227,7 @@ void compile_dllfunc_callbacks()
for (auto& cd : g_dllfunc_cdata) {
jitdata.pfn_original = *(size_t *)(size_t(g_GameDLL.funcs.dllapi_table) + cd.offset);
jitdata.args_count = cd.args_count;
jitdata.has_ret = cd.has_ret;
jitdata.rettype = cd.rettype;
jitdata.has_varargs = cd.has_varargs;
jitdata.pfn_offset = cd.offset;
jitdata.mm_hook_time = cd.mm_hook_time;
Expand All @@ -251,7 +251,7 @@ void compile_newdllfunc_callbacks()
for (auto& cd : g_newdllfunc_cdata) {
jitdata.pfn_original = g_GameDLL.funcs.newapi_table ? *(size_t *)(size_t(g_GameDLL.funcs.newapi_table) + cd.offset) : 0;
jitdata.args_count = cd.args_count;
jitdata.has_ret = cd.has_ret;
jitdata.rettype = cd.rettype;
jitdata.has_varargs = cd.has_varargs;
jitdata.pfn_offset = cd.offset;
jitdata.mm_hook_time = cd.mm_hook_time;
Expand Down
2 changes: 1 addition & 1 deletion metamod/src/engine_api.cpp
Expand Up @@ -202,7 +202,7 @@ void compile_engfuncs_callbacks()
for (auto& cd : g_engfuncs_cdata) {
jitdata.pfn_original = *(size_t *)(size_t(&g_engfuncs) + cd.offset);
jitdata.args_count = cd.args_count;
jitdata.has_ret = cd.has_ret;
jitdata.rettype = cd.rettype;
jitdata.has_varargs = cd.has_varargs;
jitdata.pfn_offset = cd.offset;
jitdata.mm_hook_time = cd.mm_hook_time;
Expand Down

0 comments on commit 80555d3

Please sign in to comment.