2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2024-12-26 14:45:34 +03:00

Add float return type support (lol :D)

This commit is contained in:
Asmodai 2018-01-26 20:42:31 +03:00
parent 76f64ff95d
commit 80555d35b8
4 changed files with 71 additions and 26 deletions

View File

@ -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) {
@ -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);
@ -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);
@ -181,7 +187,7 @@ 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
@ -189,10 +195,18 @@ void CForwardCallbackJIT::naked_main()
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);
@ -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);
@ -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);
@ -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) {

View File

@ -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;
@ -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;
@ -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 ...t_args>
rettype_t getRetType(float (*)(t_args...))
{
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;
}
template<typename ret_t, typename ...t_args>
bool is_void(ret_t (*)(t_args...))
{
return false;
return rt_integer;
}
template<typename ret_t, typename ...t_args>

View File

@ -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;
@ -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;

View File

@ -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;