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; FArgumentList *ArgList;
public: public:
FxGlobalFunctionCall(FName fname, FArgumentList *args, const FScriptPosition &pos); FxFlopFunctionCall(int index, FArgumentList *args, const FScriptPosition &pos);
~FxGlobalFunctionCall(); ~FxFlopFunctionCall();
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build); ExpEmit Emit(VMFunctionBuilder *build);
}; };

View File

@ -54,6 +54,22 @@
#include "vmbuilder.h" #include "vmbuilder.h"
#include "v_text.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) ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false) : 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. // There's currently only 3 global functions.
// If this changes later, it won't be here! // 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) if (Self != NULL)
{ {
@ -3156,11 +3174,12 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
delete this; delete this;
return NULL; return NULL;
} }
FxExpression *x = new FxGlobalFunctionCall(MethodName, ArgList, ScriptPosition); FxExpression *x = new FxFlopFunctionCall(i, ArgList, ScriptPosition);
ArgList = NULL; ArgList = NULL;
delete this; delete this;
return x->Resolve(ctx); return x->Resolve(ctx);
} }
}
int min, max, special; int min, max, special;
if (MethodName == NAME_ACS_NamedExecuteWithResult || MethodName == NAME_CallACS) 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) : FxExpression(pos)
{ {
Name = fname; assert(index >= 0 && index < countof(FxFlops) && "FLOP index out of range");
Index = index;
ArgList = args; ArgList = args;
} }
@ -3496,18 +3516,18 @@ FxGlobalFunctionCall::FxGlobalFunctionCall(FName fname, FArgumentList *args, con
// //
//========================================================================== //==========================================================================
FxGlobalFunctionCall::~FxGlobalFunctionCall() FxFlopFunctionCall::~FxFlopFunctionCall()
{ {
SAFE_DELETE(ArgList); SAFE_DELETE(ArgList);
} }
FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx) FxExpression *FxFlopFunctionCall::Resolve(FCompileContext& ctx)
{ {
CHECKRESOLVED(); CHECKRESOLVED();
if (ArgList == NULL || ArgList->Size() != 1) 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; delete this;
return NULL; return NULL;
} }
@ -3528,15 +3548,7 @@ FxExpression *FxGlobalFunctionCall::Resolve(FCompileContext& ctx)
if ((*ArgList)[0]->isConstant()) if ((*ArgList)[0]->isConstant())
{ {
double v = static_cast<FxConstant *>((*ArgList)[0])->GetValue().GetFloat(); double v = static_cast<FxConstant *>((*ArgList)[0])->GetValue().GetFloat();
if (Name == NAME_Sqrt) v = FxFlops[Index].Evaluate(v);
{
v = sqrt(v);
}
else
{
v *= M_PI / 180.0; // convert from degrees to radians
v = (Name == NAME_Sin) ? sin(v) : cos(v);
}
FxExpression *x = new FxConstant(v, ScriptPosition); FxExpression *x = new FxConstant(v, ScriptPosition);
delete this; delete this;
return x; 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); ExpEmit v = (*ArgList)[0]->Emit(build);
assert(!v.Konst && v.RegType == REGT_FLOAT); assert(!v.Konst && v.RegType == REGT_FLOAT);
build->Emit(OP_FLOP, v.RegNum, v.RegNum, build->Emit(OP_FLOP, v.RegNum, v.RegNum, FxFlops[Index].Flop);
(Name == NAME_Sqrt) ? FLOP_SQRT :
(Name == NAME_Sin) ? FLOP_SIN_DEG :
FLOP_COS_DEG);
return v; return v;
} }