mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
- implemented the '<>=' operator - more as a VM coding exercise than for its usefulness, though.
This commit is contained in:
parent
9f260983c7
commit
f5e4c4b109
3 changed files with 110 additions and 1 deletions
|
@ -2678,6 +2678,98 @@ ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxLtGtEq::FxLtGtEq(FxExpression *l, FxExpression *r)
|
||||
: FxBinary(TK_LtGtEq, l, r)
|
||||
{
|
||||
ValueType = TypeSInt32;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxLtGtEq::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
if (!ResolveLR(ctx, false)) return NULL;
|
||||
|
||||
if (!left->IsNumeric() || !right->IsNumeric())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "<>= expects two numeric operands");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (left->ValueType->GetRegType() != right->ValueType->GetRegType())
|
||||
{
|
||||
if (left->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
left = new FxFloatCast(left);
|
||||
SAFE_RESOLVE(left, ctx);
|
||||
}
|
||||
if (right->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
right = new FxFloatCast(left);
|
||||
SAFE_RESOLVE(left, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
else if (left->isConstant() && right->isConstant())
|
||||
{
|
||||
// let's cut this short and always compare doubles. For integers the result will be exactly the same as with an integer comparison, either signed or unsigned.
|
||||
auto v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
||||
auto v2 = static_cast<FxConstant *>(right)->GetValue().GetFloat();
|
||||
auto e = new FxConstant(v1 < v2 ? -1 : v1 > v2 ? 1 : 0, ScriptPosition);
|
||||
delete this;
|
||||
return e;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxLtGtEq::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit op1 = left->Emit(build);
|
||||
ExpEmit op2 = right->Emit(build);
|
||||
|
||||
assert(op1.RegType == op2.RegType);
|
||||
assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT);
|
||||
assert(!op1.Konst || !op2.Konst);
|
||||
|
||||
ExpEmit to(build, REGT_INT);
|
||||
|
||||
int instr = op1.RegType == REGT_INT ? (left->ValueType == TypeUInt32? OP_LTU_RR : OP_LT_RR) : OP_LTF_RR;
|
||||
if (op1.Konst) instr += 2;
|
||||
if (op2.Konst) instr++;
|
||||
|
||||
|
||||
build->Emit(OP_LI, to.RegNum, 1); // default to 1
|
||||
build->Emit(instr, 0, op1.RegNum, op2.RegNum); // if (left < right)
|
||||
auto j1 = build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, -1); // result is -1
|
||||
auto j2 = build->Emit(OP_JMP, 1); // jump to end
|
||||
build->BackpatchToHere(j1);
|
||||
build->Emit(instr + OP_LE_RR - OP_LT_RR, 0, op1.RegNum, op2.RegNum); // if (left == right)
|
||||
auto j3 = build->Emit(OP_JMP, 1);
|
||||
build->Emit(OP_LI, to.RegNum, 0); // result is 0
|
||||
build->BackpatchToHere(j2);
|
||||
build->BackpatchToHere(j3);
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxBinaryLogical::FxBinaryLogical(int o, FxExpression *l, FxExpression *r)
|
||||
: FxExpression(l->ScriptPosition)
|
||||
{
|
||||
|
|
|
@ -769,6 +769,21 @@ public:
|
|||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxLtGtEq : public FxBinary
|
||||
{
|
||||
public:
|
||||
FxLtGtEq(FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxBinaryLogical
|
||||
|
|
|
@ -2547,8 +2547,10 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
|||
case PEX_XorAssign:
|
||||
return ModifyAssign(new FxBinaryInt(tok, new FxAssignSelf(*ast), right), left);
|
||||
|
||||
// todo: These do not have representations in DECORATE and no implementation exists yet.
|
||||
case PEX_LTGTEQ:
|
||||
return new FxLtGtEq(left, right);
|
||||
|
||||
// todo: These do not have representations in DECORATE and no implementation exists yet.
|
||||
case PEX_Concat:
|
||||
case PEX_Is:
|
||||
// more esoteric operators
|
||||
|
|
Loading…
Reference in a new issue