mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Tablified the DECORATE floating point operations (sqrt,cos,sin)
This commit is contained in:
parent
d8d3889452
commit
8ee820042f
2 changed files with 41 additions and 32 deletions
|
@ -830,19 +830,19 @@ public:
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxGlobalFunctionCall
|
||||
// FxFlopFunctionCall
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxGlobalFunctionCall : public FxExpression
|
||||
class FxFlopFunctionCall : public FxExpression
|
||||
{
|
||||
FName Name;
|
||||
int Index;
|
||||
FArgumentList *ArgList;
|
||||
|
||||
public:
|
||||
|
||||
FxGlobalFunctionCall(FName fname, FArgumentList *args, const FScriptPosition &pos);
|
||||
~FxGlobalFunctionCall();
|
||||
FxFlopFunctionCall(int index, FArgumentList *args, const FScriptPosition &pos);
|
||||
~FxFlopFunctionCall();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
|
|
@ -54,6 +54,22 @@
|
|||
#include "vmbuilder.h"
|
||||
#include "v_text.h"
|
||||
|
||||
struct FLOP
|
||||
{
|
||||
ENamedName Name;
|
||||
int Flop;
|
||||
double (*Evaluate)(double);
|
||||
};
|
||||
|
||||
// Decorate operates on degrees, so the evaluate functions need to convert
|
||||
// degrees to radians for those that work with angles.
|
||||
static const FLOP FxFlops[] =
|
||||
{
|
||||
{ NAME_Sqrt, FLOP_SQRT, [](double v) { return sqrt(v); } },
|
||||
{ NAME_Cos, FLOP_COS_DEG, [](double v) { return cos(v * (M_PI / 180.0)); } },
|
||||
{ NAME_Sin, FLOP_SIN_DEG, [](double v) { return sin(v * (M_PI / 180.0)); } },
|
||||
};
|
||||
|
||||
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
|
||||
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false)
|
||||
{
|
||||
|
@ -3148,7 +3164,9 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
// There's currently only 3 global functions.
|
||||
// If this changes later, it won't be here!
|
||||
if (MethodName == NAME_Sin || MethodName == NAME_Cos || MethodName == NAME_Sqrt)
|
||||
for (int i = 0; i < countof(FxFlops); ++i)
|
||||
{
|
||||
if (MethodName == FxFlops[i].Name)
|
||||
{
|
||||
if (Self != NULL)
|
||||
{
|
||||
|
@ -3156,11 +3174,12 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
FxExpression *x = new FxGlobalFunctionCall(MethodName, ArgList, ScriptPosition);
|
||||
FxExpression *x = new FxFlopFunctionCall(i, ArgList, ScriptPosition);
|
||||
ArgList = NULL;
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int min, max, special;
|
||||
if (MethodName == NAME_ACS_NamedExecuteWithResult || MethodName == NAME_CallACS)
|
||||
|
@ -3483,10 +3502,11 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build, bool tailcall)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxGlobalFunctionCall::FxGlobalFunctionCall(FName fname, FArgumentList *args, const FScriptPosition &pos)
|
||||
FxFlopFunctionCall::FxFlopFunctionCall(int index, FArgumentList *args, const FScriptPosition &pos)
|
||||
: FxExpression(pos)
|
||||
{
|
||||
Name = fname;
|
||||
assert(index >= 0 && index < countof(FxFlops) && "FLOP index out of range");
|
||||
Index = index;
|
||||
ArgList = args;
|
||||
}
|
||||
|
||||
|
@ -3496,18 +3516,18 @@ FxGlobalFunctionCall::FxGlobalFunctionCall(FName fname, FArgumentList *args, con
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxGlobalFunctionCall::~FxGlobalFunctionCall()
|
||||
FxFlopFunctionCall::~FxFlopFunctionCall()
|
||||
{
|
||||
SAFE_DELETE(ArgList);
|
||||
}
|
||||
|
||||
FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx)
|
||||
FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
if (ArgList == NULL || ArgList->Size() != 1)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", Name.GetChars());
|
||||
ScriptPosition.Message(MSG_ERROR, "%s only has one parameter", FName(FxFlops[Index].Name).GetChars());
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3528,15 +3548,7 @@ FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx)
|
|||
if ((*ArgList)[0]->isConstant())
|
||||
{
|
||||
double v = static_cast<FxConstant *>((*ArgList)[0])->GetValue().GetFloat();
|
||||
if (Name == NAME_Sqrt)
|
||||
{
|
||||
v = sqrt(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
v *= M_PI / 180.0; // convert from degrees to radians
|
||||
v = (Name == NAME_Sin) ? sin(v) : cos(v);
|
||||
}
|
||||
v = FxFlops[Index].Evaluate(v);
|
||||
FxExpression *x = new FxConstant(v, ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
|
@ -3554,15 +3566,12 @@ FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxGlobalFunctionCall::Emit(VMFunctionBuilder *build)
|
||||
ExpEmit FxFlopFunctionCall::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit v = (*ArgList)[0]->Emit(build);
|
||||
assert(!v.Konst && v.RegType == REGT_FLOAT);
|
||||
|
||||
build->Emit(OP_FLOP, v.RegNum, v.RegNum,
|
||||
(Name == NAME_Sqrt) ? FLOP_SQRT :
|
||||
(Name == NAME_Sin) ? FLOP_SIN_DEG :
|
||||
FLOP_COS_DEG);
|
||||
build->Emit(OP_FLOP, v.RegNum, v.RegNum, FxFlops[Index].Flop);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue