133 lines
2.9 KiB
C++
133 lines
2.9 KiB
C++
// vim: set ts=4 sw=4 tw=99 noet:
|
|
//
|
|
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
|
|
// Copyright (C) The AMX Mod X Development Team.
|
|
//
|
|
// This software is licensed under the GNU General Public License, version 3 or higher.
|
|
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
|
// https://alliedmods.net/amxmodx-license
|
|
|
|
#include <string.h>
|
|
#include "optimizer.h"
|
|
|
|
int g_opt_level = 0;
|
|
|
|
#define OP_SYSREQ_C 123
|
|
#define OP_NOP 134
|
|
#define OP_FLOAT_MUL 138
|
|
#define OP_FLOAT_DIV 139
|
|
#define OP_FLOAT_ADD 140
|
|
#define OP_FLOAT_SUB 141
|
|
#define OP_FLOAT_TO 142
|
|
#define OP_FLOAT_ROUND 143
|
|
#define OP_FLOAT_CMP 144
|
|
|
|
cell op_trans_table[N_Total_FloatOps] =
|
|
{
|
|
OP_FLOAT_MUL,
|
|
OP_FLOAT_DIV,
|
|
OP_FLOAT_ADD,
|
|
OP_FLOAT_SUB,
|
|
OP_FLOAT_TO,
|
|
OP_FLOAT_ROUND,
|
|
OP_FLOAT_CMP
|
|
};
|
|
|
|
void OnBrowseRelocate(AMX *amx, cell *oplist, cell *cip)
|
|
{
|
|
char *codeptr = (char *)amx->base + (long)(((AMX_HEADER *)amx->base)->cod);
|
|
|
|
//jump to the parameter;
|
|
codeptr += *cip;
|
|
|
|
int native = -1;
|
|
cell n_offs = *(cell *)codeptr;
|
|
optimizer_s *opt = (optimizer_s *)amx->usertags[UT_OPTIMIZER];
|
|
for (int i=0; i<N_Total_FloatOps; i++)
|
|
{
|
|
if (opt->natives[i] == n_offs)
|
|
{
|
|
native = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (native != -1)
|
|
{
|
|
//we're patching this:
|
|
// 0x7B 0x?? SYSREQ.C float???
|
|
//with:
|
|
// 0x8A FLOAT.MUL
|
|
// 0x86 NOP
|
|
cell new_opcodes[2];
|
|
new_opcodes[0] = op_trans_table[native];
|
|
new_opcodes[1] = OP_NOP;
|
|
codeptr -= sizeof(cell);
|
|
#if defined __GNUC__ || defined ASM32 || defined JIT
|
|
*(cell *)codeptr = oplist[new_opcodes[0]];
|
|
*(cell *)(codeptr + sizeof(cell)) = oplist[new_opcodes[1]];
|
|
#else
|
|
*(cell *)codeptr = new_opcodes[0];
|
|
*(cell *)(codeptr + sizeof(cell)) = new_opcodes[1];
|
|
#endif
|
|
}
|
|
|
|
*cip += sizeof(cell);
|
|
|
|
return;
|
|
}
|
|
|
|
#define FIND_NATIVE(name, bind) \
|
|
if (amx_FindNative(amx, name, &index) != AMX_ERR_NOTFOUND) \
|
|
opt->natives[bind] = index;
|
|
|
|
void _Setup_Optimizer_Stage2(AMX *amx, cell *oplist, cell *cip)
|
|
{
|
|
int index;
|
|
|
|
amx->usertags[UT_BROWSEHOOK] = (void *)OnBrowseRelocate;
|
|
|
|
optimizer_s *opt = new optimizer_s;
|
|
|
|
for (int i=0; i<N_Total_FloatOps; i++)
|
|
opt->natives[i] = -1;
|
|
|
|
amx->usertags[UT_OPTIMIZER] = (void *)opt;
|
|
|
|
if (g_opt_level & 1)
|
|
{
|
|
FIND_NATIVE("floatmul", N_Float_Mul);
|
|
FIND_NATIVE("floatdiv", N_Float_Div);
|
|
FIND_NATIVE("floatadd", N_Float_Add);
|
|
FIND_NATIVE("floatsub", N_Float_Sub);
|
|
}
|
|
if (g_opt_level & 4)
|
|
{
|
|
FIND_NATIVE("float", N_Float_To);
|
|
FIND_NATIVE("floatround", N_Float_Round);
|
|
}
|
|
if (g_opt_level & 2)
|
|
{
|
|
#if !defined AMD64
|
|
if (amxx_CpuSupport())
|
|
{
|
|
#endif
|
|
FIND_NATIVE("floatcmp", N_Float_Cmp);
|
|
#if !defined AMD64
|
|
} else {
|
|
g_opt_level &= ~(2);
|
|
}
|
|
#endif
|
|
}
|
|
/* we don't do these yet because of radix stuff >:\ */
|
|
//FIND_NATIVE("floatsin", N_Float_Sin);
|
|
//FIND_NATIVE("floatcos", N_Float_Cos);
|
|
//FIND_NATIVE("floattan", N_Float_Tan);
|
|
}
|
|
|
|
void SetupOptimizer(AMX *amx)
|
|
{
|
|
amx->usertags[UT_BROWSEHOOK] = (void *)_Setup_Optimizer_Stage2;
|
|
}
|
|
|