- added missing min/max unsigned instructions for the VM.

This commit is contained in:
Christoph Oelckers 2018-12-03 21:12:39 +01:00
parent 493ff5f089
commit 7df8245102
4 changed files with 74 additions and 9 deletions

View file

@ -5206,12 +5206,13 @@ FxMinMax::FxMinMax(TArray<FxExpression*> &expr, FName type, const FScriptPositio
FxExpression *FxMinMax::Resolve(FCompileContext &ctx)
{
unsigned int i;
int intcount, floatcount;
int intcount, floatcount, uintcount;
CHECKRESOLVED();
// Determine if float or int
intcount = floatcount = 0;
uintcount = intcount = floatcount = 0;
for (i = 0; i < choices.Size(); ++i)
{
RESOLVE(choices[i], ctx);
@ -5224,6 +5225,9 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx)
else if (choices[i]->IsInteger())
{
intcount++;
auto type = choices[i]->ValueType;
if (type == TypeUInt32 || type == TypeUInt16 || type == TypeUInt8 || type == TypeBool) uintcount++;
else if (choices[i]->isConstant() && static_cast<FxConstant*>(choices[i])->GetValue().GetInt() > 0) uintcount++;
}
else
{
@ -5250,7 +5254,7 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx)
}
else
{
ValueType = TypeSInt32;
ValueType = uintcount == intcount? TypeUInt32 : TypeSInt32;
}
// If at least two arguments are constants, they can be solved now.
@ -5356,18 +5360,20 @@ ExpEmit FxMinMax::Emit(VMFunctionBuilder *build)
assert(choices.Size() > 0);
assert(!choices[0]->isConstant());
assert(OP_MAXF_RK == OP_MAXF_RR+1);
assert(OP_MAX_RK == OP_MAX_RR+1);
assert(OP_MIN_RK == OP_MIN_RR+1);
assert(OP_MIN_RK == OP_MIN_RR+1);
static_assert(OP_MAXF_RK == OP_MAXF_RR+1, "maxf opcodes not continuous");
static_assert(OP_MAX_RK == OP_MAX_RR+1, "max opcodes not continuous");
static_assert(OP_MINF_RK == OP_MINF_RR+1, "minf opcodes not continuous");
static_assert(OP_MIN_RK == OP_MIN_RR+1, "min opcodes not continuous");
static_assert(OP_MAXU_RK == OP_MAXU_RR + 1, "maxu opcodes not continuous");
static_assert(OP_MINU_RK == OP_MINU_RR + 1, "minu opcodes not continuous");
if (Type == NAME_Min)
{
opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_MINF_RR : OP_MIN_RR;
opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_MINF_RR : ValueType == TypeUInt32? OP_MINU_RR : OP_MIN_RR;
}
else
{
opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_MAXF_RR : OP_MAX_RR;
opcode = ValueType->GetRegType() == REGT_FLOAT ? OP_MAXF_RR : ValueType == TypeUInt32 ? OP_MAXU_RR : OP_MAX_RR;
}
ExpEmit firstreg = choices[0]->Emit(build);

View file

@ -483,6 +483,44 @@ void JitCompiler::EmitMAX_RK()
cc.cmovg(regD[A], rc);
}
void JitCompiler::EmitMINU_RR()
{
auto rc = CheckRegD(C, A);
if (A != B)
cc.mov(regD[A], regD[B]);
cc.cmp(rc, regD[A]);
cc.cmovb(regD[A], rc);
}
void JitCompiler::EmitMINU_RK()
{
auto rc = newTempInt32();
if (A != B)
cc.mov(regD[A], regD[B]);
cc.mov(rc, asmjit::imm(konstd[C]));
cc.cmp(rc, regD[A]);
cc.cmovb(regD[A], rc);
}
void JitCompiler::EmitMAXU_RR()
{
auto rc = CheckRegD(C, A);
if (A != B)
cc.mov(regD[A], regD[B]);
cc.cmp(rc, regD[A]);
cc.cmova(regD[A], rc);
}
void JitCompiler::EmitMAXU_RK()
{
auto rc = newTempInt32();
if (A != B)
cc.mov(regD[A], regD[B]);
cc.mov(rc, asmjit::imm(konstd[C]));
cc.cmp(rc, regD[A]);
cc.cmova(regD[A], rc);
}
void JitCompiler::EmitABS()
{
auto srcB = CheckRegD(B, A);

View file

@ -1163,6 +1163,23 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret)
reg.d[a] = reg.d[B] > konstd[C] ? reg.d[B] : konstd[C];
NEXTOP;
OP(MINU_RR) :
ASSERTD(a); ASSERTD(B); ASSERTD(C);
reg.d[a] = (unsigned)reg.d[B] < (unsigned)reg.d[C] ? reg.d[B] : reg.d[C];
NEXTOP;
OP(MINU_RK) :
ASSERTD(a); ASSERTD(B); ASSERTKD(C);
reg.d[a] = (unsigned)reg.d[B] < (unsigned)konstd[C] ? reg.d[B] : konstd[C];
NEXTOP;
OP(MAXU_RR) :
ASSERTD(a); ASSERTD(B); ASSERTD(C);
reg.d[a] = (unsigned)reg.d[B] > (unsigned)reg.d[C] ? reg.d[B] : reg.d[C];
NEXTOP;
OP(MAXU_RK) :
ASSERTD(a); ASSERTD(B); ASSERTKD(C);
reg.d[a] = (unsigned)reg.d[B] > (unsigned)konstd[C] ? reg.d[B] : konstd[C];
NEXTOP;
OP(ABS):
ASSERTD(a); ASSERTD(B);
reg.d[a] = abs(reg.d[B]);

View file

@ -169,6 +169,10 @@ xx(MIN_RR, min, RIRIRI, NOP, 0, 0) // dA = min(dB,dkC)
xx(MIN_RK, min, RIRIKI, MIN_RR, 4, REGT_INT)
xx(MAX_RR, max, RIRIRI, NOP, 0, 0) // dA = max(dB,dkC)
xx(MAX_RK, max, RIRIKI, MAX_RR, 4, REGT_INT)
xx(MINU_RR, minu, RIRIRI, NOP, 0, 0) // dA = min(dB,dkC) unsigned
xx(MINU_RK, minu, RIRIKI, MIN_RR, 4, REGT_INT)
xx(MAXU_RR, maxu, RIRIRI, NOP, 0, 0) // dA = max(dB,dkC) unsigned
xx(MAXU_RK, maxu, RIRIKI, MAX_RR, 4, REGT_INT)
xx(ABS, abs, RIRI, NOP, 0, 0) // dA = abs(dB)
xx(NEG, neg, RIRI, NOP, 0, 0) // dA = -dB
xx(NOT, not, RIRI, NOP, 0, 0) // dA = ~dB