mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-25 05:21:02 +00:00
- cleaned up FxCompareRel::Resolve. Also added unsigned integer support to it and FxMulDiv (these, aside from the float cast, are the only two operations where this is important.)
This commit is contained in:
parent
b6801d526b
commit
d9953eb3bd
2 changed files with 80 additions and 19 deletions
|
@ -2922,9 +2922,18 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
assert(ValueType->GetRegType() == REGT_INT);
|
assert(ValueType->GetRegType() == REGT_INT);
|
||||||
assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT);
|
assert(op1.RegType == REGT_INT && op2.RegType == REGT_INT);
|
||||||
build->Emit(Operator == '/' ? (op1.Konst ? OP_DIV_KR : op2.Konst ? OP_DIV_RK : OP_DIV_RR)
|
if (ValueType == TypeUInt32)
|
||||||
: (op1.Konst ? OP_MOD_KR : op2.Konst ? OP_MOD_RK : OP_MOD_RR),
|
{
|
||||||
to.RegNum, op1.RegNum, op2.RegNum);
|
build->Emit(Operator == '/' ? (op1.Konst ? OP_DIVU_KR : op2.Konst ? OP_DIVU_RK : OP_DIVU_RR)
|
||||||
|
: (op1.Konst ? OP_MODU_KR : op2.Konst ? OP_MODU_RK : OP_MODU_RR),
|
||||||
|
to.RegNum, op1.RegNum, op2.RegNum);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
build->Emit(Operator == '/' ? (op1.Konst ? OP_DIV_KR : op2.Konst ? OP_DIV_RK : OP_DIV_RR)
|
||||||
|
: (op1.Konst ? OP_MOD_KR : op2.Konst ? OP_MOD_RK : OP_MOD_RR),
|
||||||
|
to.RegNum, op1.RegNum, op2.RegNum);
|
||||||
|
}
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3024,16 +3033,51 @@ FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r)
|
||||||
FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (!ResolveLR(ctx, true))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (!IsNumeric())
|
RESOLVE(left, ctx);
|
||||||
|
RESOLVE(right, ctx);
|
||||||
|
if (!left || !right)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else if (left->isConstant() && right->isConstant())
|
|
||||||
|
if (left->ValueType == TypeString || right->ValueType == TypeString)
|
||||||
|
{
|
||||||
|
if (left->ValueType != TypeString)
|
||||||
|
{
|
||||||
|
left = new FxStringCast(left);
|
||||||
|
left = left->Resolve(ctx);
|
||||||
|
if (left == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (right->ValueType != TypeString)
|
||||||
|
{
|
||||||
|
right = new FxStringCast(right);
|
||||||
|
right = right->Resolve(ctx);
|
||||||
|
if (right == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueType == TypeString;
|
||||||
|
}
|
||||||
|
else if (left->IsNumeric() && right->IsNumeric())
|
||||||
|
{
|
||||||
|
Promote(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Incompatible operands for relative comparison");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left->isConstant() && right->isConstant())
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
|
@ -3056,20 +3100,29 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
||||||
Operator == TK_Geq? v1 >= v2 :
|
Operator == TK_Geq? v1 >= v2 :
|
||||||
Operator == TK_Leq? v1 <= v2 : 0;
|
Operator == TK_Leq? v1 <= v2 : 0;
|
||||||
}
|
}
|
||||||
else
|
else if (ValueType == TypeUInt32)
|
||||||
{
|
{
|
||||||
int v1 = static_cast<FxConstant *>(left)->GetValue().GetInt();
|
int v1 = static_cast<FxConstant *>(left)->GetValue().GetUInt();
|
||||||
int v2 = static_cast<FxConstant *>(right)->GetValue().GetInt();
|
int v2 = static_cast<FxConstant *>(right)->GetValue().GetUInt();
|
||||||
v = Operator == '<'? v1 < v2 :
|
v = Operator == '<'? v1 < v2 :
|
||||||
Operator == '>'? v1 > v2 :
|
Operator == '>'? v1 > v2 :
|
||||||
Operator == TK_Geq? v1 >= v2 :
|
Operator == TK_Geq? v1 >= v2 :
|
||||||
Operator == TK_Leq? v1 <= v2 : 0;
|
Operator == TK_Leq? v1 <= v2 : 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int v1 = static_cast<FxConstant *>(left)->GetValue().GetInt();
|
||||||
|
int v2 = static_cast<FxConstant *>(right)->GetValue().GetInt();
|
||||||
|
v = Operator == '<' ? v1 < v2 :
|
||||||
|
Operator == '>' ? v1 > v2 :
|
||||||
|
Operator == TK_Geq ? v1 >= v2 :
|
||||||
|
Operator == TK_Leq ? v1 <= v2 : 0;
|
||||||
|
}
|
||||||
FxExpression *e = new FxConstant(v, ScriptPosition);
|
FxExpression *e = new FxConstant(v, ScriptPosition);
|
||||||
delete this;
|
delete this;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
Promote(ctx);
|
CompareType = ValueType; // needs to be preserved for detection of unsigned compare.
|
||||||
ValueType = TypeBool;
|
ValueType = TypeBool;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -3124,10 +3177,10 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||||
assert(Operator == '<' || Operator == '>' || Operator == TK_Geq || Operator == TK_Leq);
|
assert(Operator == '<' || Operator == '>' || Operator == TK_Geq || Operator == TK_Leq);
|
||||||
static const VM_UBYTE InstrMap[][4] =
|
static const VM_UBYTE InstrMap[][4] =
|
||||||
{
|
{
|
||||||
{ OP_LT_RR, OP_LTF_RR, 0 }, // <
|
{ OP_LT_RR, OP_LTF_RR, OP_LTU_RR, 0 }, // <
|
||||||
{ OP_LE_RR, OP_LEF_RR, 1 }, // >
|
{ OP_LE_RR, OP_LEF_RR, OP_LEU_RR, 1 }, // >
|
||||||
{ OP_LT_RR, OP_LTF_RR, 1 }, // >=
|
{ OP_LT_RR, OP_LTF_RR, OP_LTU_RR, 1 }, // >=
|
||||||
{ OP_LE_RR, OP_LEF_RR, 0 } // <=
|
{ OP_LE_RR, OP_LEF_RR, OP_LEU_RR, 0 } // <=
|
||||||
};
|
};
|
||||||
int instr, check;
|
int instr, check;
|
||||||
ExpEmit to(build, REGT_INT);
|
ExpEmit to(build, REGT_INT);
|
||||||
|
@ -3135,8 +3188,9 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||||
Operator == '>' ? 1 :
|
Operator == '>' ? 1 :
|
||||||
Operator == TK_Geq ? 2 : 3;
|
Operator == TK_Geq ? 2 : 3;
|
||||||
|
|
||||||
instr = InstrMap[index][op1.RegType == REGT_INT ? 0 : 1];
|
int mode = op1.RegType == REGT_FLOAT ? 1 : CompareType == TypeUInt32 ? 2 : 0;
|
||||||
check = InstrMap[index][2];
|
instr = InstrMap[index][mode];
|
||||||
|
check = InstrMap[index][3];
|
||||||
if (op2.Konst)
|
if (op2.Konst)
|
||||||
{
|
{
|
||||||
instr += 1;
|
instr += 1;
|
||||||
|
|
|
@ -169,10 +169,16 @@ struct ExpVal
|
||||||
return regtype == REGT_INT ? Int : regtype == REGT_FLOAT ? int(Float) : 0;
|
return regtype == REGT_INT ? Int : regtype == REGT_FLOAT ? int(Float) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned GetUInt() const
|
||||||
|
{
|
||||||
|
int regtype = Type->GetRegType();
|
||||||
|
return regtype == REGT_INT ? unsigned(Int) : regtype == REGT_FLOAT ? unsigned(Float) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
double GetFloat() const
|
double GetFloat() const
|
||||||
{
|
{
|
||||||
int regtype = Type->GetRegType();
|
int regtype = Type->GetRegType();
|
||||||
return regtype == REGT_INT ? double(Int) : regtype == REGT_FLOAT ? Float : 0;
|
return regtype == REGT_INT ? (Type == TypeUInt32? double(unsigned(Int)) : double(Int)) : regtype == REGT_FLOAT ? Float : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *GetPointer() const
|
void *GetPointer() const
|
||||||
|
@ -864,6 +870,7 @@ public:
|
||||||
|
|
||||||
class FxCompareRel : public FxBinary
|
class FxCompareRel : public FxBinary
|
||||||
{
|
{
|
||||||
|
PType *CompareType;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FxCompareRel(int, FxExpression*, FxExpression*);
|
FxCompareRel(int, FxExpression*, FxExpression*);
|
||||||
|
|
Loading…
Reference in a new issue