Tablified the DECORATE floating point operations (sqrt,cos,sin)

This commit is contained in:
Randy Heit 2016-02-25 09:23:46 -06:00
parent d8d3889452
commit 8ee820042f
2 changed files with 41 additions and 32 deletions

View file

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

View file

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