mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 22:33:17 +00:00
- added missing min/max unsigned instructions for the VM.
This commit is contained in:
parent
493ff5f089
commit
7df8245102
4 changed files with 74 additions and 9 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue