mirror of
https://github.com/sp-tarkov/assembly-tool.git
synced 2025-02-13 06:30:44 -05:00
Adds the source code used for this modification, this de4dot source code has been cleaned of any things not needed for deobfuscating the tarkov assembly Co-authored-by: 静穏靄 <170472707+seionmoya@users.noreply.github.com>
623 lines
19 KiB
C#
623 lines
19 KiB
C#
/*
|
|
Copyright (C) 2011-2015 de4dot@gmail.com
|
|
|
|
This file is part of de4dot.
|
|
|
|
de4dot is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
de4dot is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using System;
|
|
|
|
namespace de4dot.blocks.cflow {
|
|
public class Int32Value : Value {
|
|
public static readonly Int32Value Zero = new Int32Value(0);
|
|
public static readonly Int32Value One = new Int32Value(1);
|
|
|
|
internal const uint NO_UNKNOWN_BITS = uint.MaxValue;
|
|
public readonly int Value;
|
|
public readonly uint ValidMask;
|
|
|
|
public Int32Value(int value)
|
|
: base(ValueType.Int32) {
|
|
Value = value;
|
|
ValidMask = NO_UNKNOWN_BITS;
|
|
}
|
|
|
|
public Int32Value(int value, uint validMask)
|
|
: base(ValueType.Int32) {
|
|
Value = value;
|
|
ValidMask = validMask;
|
|
}
|
|
|
|
public bool HasUnknownBits() => ValidMask != NO_UNKNOWN_BITS;
|
|
public bool AllBitsValid() => !HasUnknownBits();
|
|
bool IsBitValid(int n) => IsBitValid(ValidMask, n);
|
|
static bool IsBitValid(uint validMask, int n) => (validMask & (1U << n)) != 0;
|
|
bool AreBitsValid(uint bitsToTest) => (ValidMask & bitsToTest) == bitsToTest;
|
|
public static Int32Value CreateUnknownBool() => new Int32Value(0, NO_UNKNOWN_BITS << 1);
|
|
public static Int32Value CreateUnknownUInt8() => new Int32Value(0, NO_UNKNOWN_BITS << 8);
|
|
public static Int32Value CreateUnknownUInt16() => new Int32Value(0, NO_UNKNOWN_BITS << 16);
|
|
public static Int32Value CreateUnknown() => new Int32Value(0, 0U);
|
|
public bool IsZero() => HasValue(0);
|
|
public bool IsNonZero() => ((uint)Value & ValidMask) != 0;
|
|
public bool HasValue(int value) => AllBitsValid() && Value == value;
|
|
public bool HasValue(uint value) => HasValue((int)value);
|
|
|
|
public Int32Value ToBoolean() {
|
|
if (IsNonZero())
|
|
return new Int32Value(1, NO_UNKNOWN_BITS);
|
|
if (IsZero())
|
|
return this;
|
|
return CreateUnknownBool();
|
|
}
|
|
|
|
public Int32Value ToInt8() => Conv_I1(this);
|
|
public Int32Value ToUInt8() => Conv_U1(this);
|
|
public Int32Value ToInt16() => Conv_I2(this);
|
|
public Int32Value ToUInt16() => Conv_U2(this);
|
|
public static Int32Value Conv_U1(Int32Value a) => Conv_U1(a.Value, a.ValidMask);
|
|
public static Int32Value Conv_U1(Int64Value a) => Conv_U1((int)a.Value, (uint)a.ValidMask);
|
|
|
|
public static Int32Value Conv_U1(int value, uint validMask) {
|
|
value = (int)(byte)value;
|
|
validMask |= NO_UNKNOWN_BITS << 8;
|
|
return new Int32Value(value, validMask);
|
|
}
|
|
|
|
public static Int32Value Conv_U1(Real8Value a) {
|
|
if (!a.IsValid)
|
|
return CreateUnknownUInt8();
|
|
return new Int32Value((int)(byte)a.Value);
|
|
}
|
|
|
|
public static Int32Value Conv_I1(Int32Value a) => Conv_I1(a.Value, a.ValidMask);
|
|
public static Int32Value Conv_I1(Int64Value a) => Conv_I1((int)a.Value, (uint)a.ValidMask);
|
|
|
|
public static Int32Value Conv_I1(int value, uint validMask) {
|
|
value = (int)(sbyte)value;
|
|
if (IsBitValid(validMask, 7))
|
|
validMask |= NO_UNKNOWN_BITS << 8;
|
|
else
|
|
validMask &= ~(NO_UNKNOWN_BITS << 8);
|
|
return new Int32Value(value, validMask);
|
|
}
|
|
|
|
public static Int32Value Conv_I1(Real8Value a) {
|
|
if (!a.IsValid)
|
|
return CreateUnknown();
|
|
return new Int32Value((int)(sbyte)a.Value);
|
|
}
|
|
|
|
public static Int32Value Conv_U2(Int32Value a) => Conv_U2(a.Value, a.ValidMask);
|
|
public static Int32Value Conv_U2(Int64Value a) => Conv_U2((int)a.Value, (uint)a.ValidMask);
|
|
|
|
public static Int32Value Conv_U2(int value, uint validMask) {
|
|
value = (int)(ushort)value;
|
|
validMask |= NO_UNKNOWN_BITS << 16;
|
|
return new Int32Value(value, validMask);
|
|
}
|
|
|
|
public static Int32Value Conv_U2(Real8Value a) {
|
|
if (!a.IsValid)
|
|
return CreateUnknownUInt16();
|
|
return new Int32Value((int)(ushort)a.Value);
|
|
}
|
|
|
|
public static Int32Value Conv_I2(Int32Value a) => Conv_I2(a.Value, a.ValidMask);
|
|
public static Int32Value Conv_I2(Int64Value a) => Conv_I2((int)a.Value, (uint)a.ValidMask);
|
|
|
|
public static Int32Value Conv_I2(int value, uint validMask) {
|
|
value = (int)(short)value;
|
|
if (IsBitValid(validMask, 15))
|
|
validMask |= NO_UNKNOWN_BITS << 16;
|
|
else
|
|
validMask &= ~(NO_UNKNOWN_BITS << 16);
|
|
return new Int32Value(value, validMask);
|
|
}
|
|
|
|
public static Int32Value Conv_I2(Real8Value a) {
|
|
if (!a.IsValid)
|
|
return CreateUnknown();
|
|
return new Int32Value((int)(short)a.Value);
|
|
}
|
|
|
|
public static Int32Value Conv_U4(Int32Value a) => a;
|
|
public static Int32Value Conv_U4(Int64Value a) => new Int32Value((int)(uint)a.Value, (uint)a.ValidMask);
|
|
public static Int32Value Conv_U4(Real8Value a) {
|
|
if (!a.IsValid)
|
|
return CreateUnknown();
|
|
return new Int32Value((int)(uint)a.Value);
|
|
}
|
|
|
|
public static Int32Value Conv_I4(Int32Value a) => a;
|
|
public static Int32Value Conv_I4(Int64Value a) => new Int32Value((int)a.Value, (uint)a.ValidMask);
|
|
|
|
public static Int32Value Conv_I4(Real8Value a) {
|
|
if (!a.IsValid)
|
|
return CreateUnknown();
|
|
return new Int32Value((int)a.Value);
|
|
}
|
|
|
|
bool CheckSign(uint mask) => ((uint)Value & mask) == 0 || ((uint)Value & mask) == mask;
|
|
|
|
public static Int32Value Conv_Ovf_I1(Int32Value a) {
|
|
if (!a.AreBitsValid(NO_UNKNOWN_BITS << 7) ||
|
|
!a.CheckSign(NO_UNKNOWN_BITS << 7))
|
|
return CreateUnknown();
|
|
return Conv_I1(a);
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_I1_Un(Int32Value a) {
|
|
if (!a.AreBitsValid(NO_UNKNOWN_BITS << 7) ||
|
|
(uint)a.Value > sbyte.MaxValue)
|
|
return CreateUnknown();
|
|
return Conv_I1(a);
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_I2(Int32Value a) {
|
|
if (!a.AreBitsValid(NO_UNKNOWN_BITS << 15) ||
|
|
!a.CheckSign(NO_UNKNOWN_BITS << 15))
|
|
return CreateUnknown();
|
|
return Conv_I2(a);
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_I2_Un(Int32Value a) {
|
|
if (!a.AreBitsValid(NO_UNKNOWN_BITS << 15) ||
|
|
(uint)a.Value > short.MaxValue)
|
|
return CreateUnknown();
|
|
return Conv_I2(a);
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_I4(Int32Value a) => a;
|
|
|
|
public static Int32Value Conv_Ovf_I4_Un(Int32Value a) {
|
|
if (!IsBitValid(a.ValidMask, 31) || a.Value < 0)
|
|
return CreateUnknown();
|
|
return a;
|
|
}
|
|
|
|
public static Int64Value Conv_Ovf_I8(Int32Value a) {
|
|
ulong validMask = a.ValidMask;
|
|
if (IsBitValid(a.ValidMask, 31))
|
|
validMask |= Int64Value.NO_UNKNOWN_BITS << 32;
|
|
return new Int64Value(a.Value, validMask);
|
|
}
|
|
|
|
public static Int64Value Conv_Ovf_I8_Un(Int32Value a) =>
|
|
new Int64Value((long)(uint)a.Value, a.ValidMask | (Int64Value.NO_UNKNOWN_BITS << 32));
|
|
|
|
public static Int32Value Conv_Ovf_U1(Int32Value a) {
|
|
if (!a.AreBitsValid(NO_UNKNOWN_BITS << 7) ||
|
|
a.Value < 0 || a.Value > byte.MaxValue)
|
|
return CreateUnknownUInt8();
|
|
return Conv_U1(a);
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_U1_Un(Int32Value a) {
|
|
if (!a.AreBitsValid(NO_UNKNOWN_BITS << 8) ||
|
|
(uint)a.Value > byte.MaxValue)
|
|
return CreateUnknownUInt8();
|
|
return Conv_U1(a);
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_U2(Int32Value a) {
|
|
if (!a.AreBitsValid(NO_UNKNOWN_BITS << 15) ||
|
|
a.Value < 0 || a.Value > ushort.MaxValue)
|
|
return CreateUnknownUInt16();
|
|
return Conv_U2(a);
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_U2_Un(Int32Value a) {
|
|
if (!a.AreBitsValid(NO_UNKNOWN_BITS << 16) ||
|
|
(uint)a.Value > ushort.MaxValue)
|
|
return CreateUnknownUInt16();
|
|
return Conv_U2(a);
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_U4(Int32Value a) {
|
|
if (!IsBitValid(a.ValidMask, 31) || a.Value < 0)
|
|
return CreateUnknown();
|
|
return a;
|
|
}
|
|
|
|
public static Int32Value Conv_Ovf_U4_Un(Int32Value a) => a;
|
|
|
|
public static Int64Value Conv_Ovf_U8(Int32Value a) {
|
|
if (!IsBitValid(a.ValidMask, 31) || a.Value < 0)
|
|
return Int64Value.CreateUnknown();
|
|
return new Int64Value(a.Value, (ulong)a.ValidMask | (Int64Value.NO_UNKNOWN_BITS << 32));
|
|
}
|
|
|
|
public static Int64Value Conv_Ovf_U8_Un(Int32Value a) =>
|
|
new Int64Value((long)(uint)a.Value, a.ValidMask | (Int64Value.NO_UNKNOWN_BITS << 32));
|
|
|
|
public static Real8Value Conv_R_Un(Int32Value a) {
|
|
if (a.AllBitsValid())
|
|
return new Real8Value((double)(uint)a.Value);
|
|
return Real8Value.CreateUnknown();
|
|
}
|
|
|
|
public static Real8Value Conv_R4(Int32Value a) {
|
|
if (a.AllBitsValid())
|
|
return new Real8Value((double)(int)a.Value);
|
|
return Real8Value.CreateUnknown();
|
|
}
|
|
|
|
public static Real8Value Conv_R8(Int32Value a) {
|
|
if (a.AllBitsValid())
|
|
return new Real8Value((double)(int)a.Value);
|
|
return Real8Value.CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Add(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return new Int32Value(a.Value + b.Value);
|
|
if (ReferenceEquals(a, b))
|
|
return new Int32Value(a.Value << 1, (a.ValidMask << 1) | 1);
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Sub(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return new Int32Value(a.Value - b.Value);
|
|
if (ReferenceEquals(a, b))
|
|
return Zero;
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Mul(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return new Int32Value(a.Value * b.Value);
|
|
if (a.IsZero() || b.IsZero())
|
|
return Zero;
|
|
if (a.HasValue(1))
|
|
return b;
|
|
if (b.HasValue(1))
|
|
return a;
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Div(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
try {
|
|
return new Int32Value(a.Value / b.Value);
|
|
}
|
|
catch (ArithmeticException) {
|
|
return CreateUnknown();
|
|
}
|
|
}
|
|
if (ReferenceEquals(a, b) && a.IsNonZero())
|
|
return One;
|
|
if (b.HasValue(1))
|
|
return a;
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Div_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
try {
|
|
return new Int32Value((int)((uint)a.Value / (uint)b.Value));
|
|
}
|
|
catch (ArithmeticException) {
|
|
return CreateUnknown();
|
|
}
|
|
}
|
|
if (ReferenceEquals(a, b) && a.IsNonZero())
|
|
return One;
|
|
if (b.HasValue(1))
|
|
return a;
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Rem(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
try {
|
|
return new Int32Value(a.Value % b.Value);
|
|
}
|
|
catch (ArithmeticException) {
|
|
return CreateUnknown();
|
|
}
|
|
}
|
|
if ((ReferenceEquals(a, b) && a.IsNonZero()) || b.HasValue(1))
|
|
return Zero;
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Rem_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
try {
|
|
return new Int32Value((int)((uint)a.Value % (uint)b.Value));
|
|
}
|
|
catch (ArithmeticException) {
|
|
return CreateUnknown();
|
|
}
|
|
}
|
|
if ((ReferenceEquals(a, b) && a.IsNonZero()) || b.HasValue(1))
|
|
return Zero;
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Neg(Int32Value a) {
|
|
if (a.AllBitsValid())
|
|
return new Int32Value(-a.Value);
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Add_Ovf(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
try {
|
|
return new Int32Value(checked(a.Value + b.Value));
|
|
}
|
|
catch (OverflowException) {
|
|
}
|
|
}
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Add_Ovf_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
uint aa = (uint)a.Value, bb = (uint)b.Value;
|
|
try {
|
|
return new Int32Value((int)checked(aa + bb));
|
|
}
|
|
catch (OverflowException) {
|
|
}
|
|
}
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Sub_Ovf(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
try {
|
|
return new Int32Value(checked(a.Value - b.Value));
|
|
}
|
|
catch (OverflowException) {
|
|
}
|
|
}
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Sub_Ovf_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
uint aa = (uint)a.Value, bb = (uint)b.Value;
|
|
try {
|
|
return new Int32Value((int)checked(aa - bb));
|
|
}
|
|
catch (OverflowException) {
|
|
}
|
|
}
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Mul_Ovf(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
try {
|
|
return new Int32Value(checked(a.Value * b.Value));
|
|
}
|
|
catch (OverflowException) {
|
|
}
|
|
}
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value Mul_Ovf_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid()) {
|
|
uint aa = (uint)a.Value, bb = (uint)b.Value;
|
|
try {
|
|
return new Int32Value((int)checked(aa * bb));
|
|
}
|
|
catch (OverflowException) {
|
|
}
|
|
}
|
|
return CreateUnknown();
|
|
}
|
|
|
|
public static Int32Value And(Int32Value a, Int32Value b) {
|
|
int av = a.Value, bv = b.Value;
|
|
uint am = a.ValidMask, bm = b.ValidMask;
|
|
return new Int32Value(av & bv, (am & bm) | (((uint)av & am) ^ am) | (((uint)bv & bm) ^ bm));
|
|
}
|
|
|
|
public static Int32Value Or(Int32Value a, Int32Value b) {
|
|
int av = a.Value, bv = b.Value;
|
|
uint am = a.ValidMask, bm = b.ValidMask;
|
|
return new Int32Value(av | bv, (am & bm) | ((uint)av & am) | ((uint)bv & bm));
|
|
}
|
|
|
|
public static Int32Value Xor(Int32Value a, Int32Value b) {
|
|
if (ReferenceEquals(a, b))
|
|
return Zero;
|
|
int av = a.Value, bv = b.Value;
|
|
uint am = a.ValidMask, bm = b.ValidMask;
|
|
return new Int32Value(av ^ bv, am & bm);
|
|
}
|
|
|
|
public static Int32Value Not(Int32Value a) => new Int32Value(~a.Value, a.ValidMask);
|
|
|
|
public static Int32Value Shl(Int32Value a, Int32Value b) {
|
|
if (b.HasUnknownBits())
|
|
return CreateUnknown();
|
|
if (b.Value == 0)
|
|
return a;
|
|
if (b.Value < 0 || b.Value >= sizeof(int) * 8)
|
|
return CreateUnknown();
|
|
int shift = b.Value;
|
|
uint validMask = (a.ValidMask << shift) | (uint.MaxValue >> (sizeof(int) * 8 - shift));
|
|
return new Int32Value(a.Value << shift, validMask);
|
|
}
|
|
|
|
public static Int32Value Shr(Int32Value a, Int32Value b) {
|
|
if (b.HasUnknownBits())
|
|
return CreateUnknown();
|
|
if (b.Value == 0)
|
|
return a;
|
|
if (b.Value < 0 || b.Value >= sizeof(int) * 8)
|
|
return CreateUnknown();
|
|
int shift = b.Value;
|
|
uint validMask = a.ValidMask >> shift;
|
|
if (a.IsBitValid(sizeof(int) * 8 - 1))
|
|
validMask |= (uint.MaxValue << (sizeof(int) * 8 - shift));
|
|
return new Int32Value(a.Value >> shift, validMask);
|
|
}
|
|
|
|
public static Int32Value Shr_Un(Int32Value a, Int32Value b) {
|
|
if (b.HasUnknownBits())
|
|
return CreateUnknown();
|
|
if (b.Value == 0)
|
|
return a;
|
|
if (b.Value < 0 || b.Value >= sizeof(int) * 8)
|
|
return CreateUnknown();
|
|
int shift = b.Value;
|
|
uint validMask = (a.ValidMask >> shift) | (uint.MaxValue << (sizeof(int) * 8 - shift));
|
|
return new Int32Value((int)((uint)a.Value >> shift), validMask);
|
|
}
|
|
|
|
public static Int32Value Create(Bool3 b) {
|
|
switch (b) {
|
|
case Bool3.False: return Zero;
|
|
case Bool3.True: return One;
|
|
default: return CreateUnknownBool();
|
|
}
|
|
}
|
|
|
|
public static Int32Value Ceq(Int32Value a, Int32Value b) => Create(CompareEq(a, b));
|
|
public static Int32Value Cgt(Int32Value a, Int32Value b) => Create(CompareGt(a, b));
|
|
public static Int32Value Cgt_Un(Int32Value a, Int32Value b) => Create(CompareGt_Un(a, b));
|
|
public static Int32Value Clt(Int32Value a, Int32Value b) => Create(CompareLt(a, b));
|
|
public static Int32Value Clt_Un(Int32Value a, Int32Value b) => Create(CompareLt_Un(a, b));
|
|
|
|
public static Bool3 CompareEq(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return a.Value == b.Value ? Bool3.True : Bool3.False;
|
|
if (ReferenceEquals(a, b))
|
|
return Bool3.True;
|
|
if (((uint)a.Value & a.ValidMask & b.ValidMask) != ((uint)b.Value & a.ValidMask & b.ValidMask))
|
|
return Bool3.False;
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareNeq(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return a.Value != b.Value ? Bool3.True : Bool3.False;
|
|
if (ReferenceEquals(a, b))
|
|
return Bool3.False;
|
|
if (((uint)a.Value & a.ValidMask & b.ValidMask) != ((uint)b.Value & a.ValidMask & b.ValidMask))
|
|
return Bool3.True;
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareGt(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return a.Value > b.Value ? Bool3.True : Bool3.False;
|
|
if (a.HasValue(int.MinValue))
|
|
return Bool3.False; // min > x => false
|
|
if (b.HasValue(int.MaxValue))
|
|
return Bool3.False; // x > max => false
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareGt_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return (uint)a.Value > (uint)b.Value ? Bool3.True : Bool3.False;
|
|
if (a.HasValue(uint.MinValue))
|
|
return Bool3.False; // min > x => false
|
|
if (b.HasValue(uint.MaxValue))
|
|
return Bool3.False; // x > max => false
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareGe(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return a.Value >= b.Value ? Bool3.True : Bool3.False;
|
|
if (a.HasValue(int.MaxValue))
|
|
return Bool3.True; // max >= x => true
|
|
if (b.HasValue(int.MinValue))
|
|
return Bool3.True; // x >= min => true
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareGe_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return (uint)a.Value >= (uint)b.Value ? Bool3.True : Bool3.False;
|
|
if (a.HasValue(uint.MaxValue))
|
|
return Bool3.True; // max >= x => true
|
|
if (b.HasValue(uint.MinValue))
|
|
return Bool3.True; // x >= min => true
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareLe(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return a.Value <= b.Value ? Bool3.True : Bool3.False;
|
|
if (a.HasValue(int.MinValue))
|
|
return Bool3.True; // min <= x => true
|
|
if (b.HasValue(int.MaxValue))
|
|
return Bool3.True; // x <= max => true
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareLe_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return (uint)a.Value <= (uint)b.Value ? Bool3.True : Bool3.False;
|
|
if (a.HasValue(uint.MinValue))
|
|
return Bool3.True; // min <= x => true
|
|
if (b.HasValue(uint.MaxValue))
|
|
return Bool3.True; // x <= max => true
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareLt(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return a.Value < b.Value ? Bool3.True : Bool3.False;
|
|
if (a.HasValue(int.MaxValue))
|
|
return Bool3.False; // max < x => false
|
|
if (b.HasValue(int.MinValue))
|
|
return Bool3.False; // x < min => false
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareLt_Un(Int32Value a, Int32Value b) {
|
|
if (a.AllBitsValid() && b.AllBitsValid())
|
|
return (uint)a.Value < (uint)b.Value ? Bool3.True : Bool3.False;
|
|
if (a.HasValue(uint.MaxValue))
|
|
return Bool3.False; // max < x => false
|
|
if (b.HasValue(uint.MinValue))
|
|
return Bool3.False; // x < min => false
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareTrue(Int32Value a) {
|
|
if (a.AllBitsValid())
|
|
return a.Value != 0 ? Bool3.True : Bool3.False;
|
|
if (((uint)a.Value & a.ValidMask) != 0)
|
|
return Bool3.True;
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public static Bool3 CompareFalse(Int32Value a) {
|
|
if (a.AllBitsValid())
|
|
return a.Value == 0 ? Bool3.True : Bool3.False;
|
|
if (((uint)a.Value & a.ValidMask) != 0)
|
|
return Bool3.False;
|
|
return Bool3.Unknown;
|
|
}
|
|
|
|
public override string ToString() {
|
|
if (AllBitsValid())
|
|
return Value.ToString();
|
|
return $"0x{Value:X8}({ValidMask:X8})";
|
|
}
|
|
}
|
|
}
|