mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 22:33:17 +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)
|
FxBinaryLogical::FxBinaryLogical(int o, FxExpression *l, FxExpression *r)
|
||||||
: FxExpression(l->ScriptPosition)
|
: FxExpression(l->ScriptPosition)
|
||||||
{
|
{
|
||||||
|
|
|
@ -769,6 +769,21 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxLtGtEq : public FxBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FxLtGtEq(FxExpression*, FxExpression*);
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FxBinaryLogical
|
// FxBinaryLogical
|
||||||
|
|
|
@ -2547,8 +2547,10 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
case PEX_XorAssign:
|
case PEX_XorAssign:
|
||||||
return ModifyAssign(new FxBinaryInt(tok, new FxAssignSelf(*ast), right), left);
|
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:
|
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_Concat:
|
||||||
case PEX_Is:
|
case PEX_Is:
|
||||||
// more esoteric operators
|
// more esoteric operators
|
||||||
|
|
Loading…
Reference in a new issue