Merge pull request #403 from lioncash/zero
Add several convenience functions to the Value class
This commit is contained in:
commit
4c6a9535ca
3 changed files with 79 additions and 14 deletions
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/bit_util.h"
|
||||||
#include "frontend/ir/microinstruction.h"
|
#include "frontend/ir/microinstruction.h"
|
||||||
#include "frontend/ir/opcodes.h"
|
#include "frontend/ir/opcodes.h"
|
||||||
#include "frontend/ir/type.h"
|
#include "frontend/ir/type.h"
|
||||||
|
@ -155,6 +156,25 @@ Cond Value::GetCond() const {
|
||||||
return inner.imm_cond;
|
return inner.imm_cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s64 Value::GetImmediateAsS64() const {
|
||||||
|
ASSERT(IsImmediate());
|
||||||
|
|
||||||
|
switch (GetType()) {
|
||||||
|
case IR::Type::U1:
|
||||||
|
return s64(GetU1());
|
||||||
|
case IR::Type::U8:
|
||||||
|
return s64(Common::SignExtend<8, u64>(GetU8()));
|
||||||
|
case IR::Type::U16:
|
||||||
|
return s64(Common::SignExtend<16, u64>(GetU16()));
|
||||||
|
case IR::Type::U32:
|
||||||
|
return s64(Common::SignExtend<32, u64>(GetU32()));
|
||||||
|
case IR::Type::U64:
|
||||||
|
return s64(GetU64());
|
||||||
|
default:
|
||||||
|
ASSERT_MSG(false, "GetImmediateAsS64 called on an incompatible Value type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u64 Value::GetImmediateAsU64() const {
|
u64 Value::GetImmediateAsU64() const {
|
||||||
ASSERT(IsImmediate());
|
ASSERT(IsImmediate());
|
||||||
|
|
||||||
|
@ -174,6 +194,14 @@ u64 Value::GetImmediateAsU64() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Value::IsSignedImmediate(s64 value) const {
|
||||||
|
return IsImmediate() && GetImmediateAsS64() == value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Value::IsUnsignedImmediate(u64 value) const {
|
||||||
|
return IsImmediate() && GetImmediateAsU64() == value;
|
||||||
|
}
|
||||||
|
|
||||||
bool Value::HasAllBitsSet() const {
|
bool Value::HasAllBitsSet() const {
|
||||||
ASSERT(IsImmediate());
|
ASSERT(IsImmediate());
|
||||||
|
|
||||||
|
@ -194,4 +222,8 @@ bool Value::HasAllBitsSet() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Value::IsZero() const {
|
||||||
|
return IsUnsignedImmediate(0);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::IR
|
} // namespace Dynarmic::IR
|
||||||
|
|
|
@ -67,13 +67,43 @@ public:
|
||||||
Cond GetCond() const;
|
Cond GetCond() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the immediate of a Value instance.
|
* Retrieves the immediate of a Value instance as a signed 64-bit value.
|
||||||
|
*
|
||||||
|
* @pre The value contains either a U1, U8, U16, U32, or U64 value.
|
||||||
|
* Breaking this precondition will cause an assertion to be invoked.
|
||||||
|
*/
|
||||||
|
s64 GetImmediateAsS64() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the immediate of a Value instance as an unsigned 64-bit value.
|
||||||
*
|
*
|
||||||
* @pre The value contains either a U1, U8, U16, U32, or U64 value.
|
* @pre The value contains either a U1, U8, U16, U32, or U64 value.
|
||||||
* Breaking this precondition will cause an assertion to be invoked.
|
* Breaking this precondition will cause an assertion to be invoked.
|
||||||
*/
|
*/
|
||||||
u64 GetImmediateAsU64() const;
|
u64 GetImmediateAsU64() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not the contained value matches the provided signed one.
|
||||||
|
*
|
||||||
|
* Note that this function will always return false if the contained
|
||||||
|
* value is not a a constant value. In other words, if IsImmediate()
|
||||||
|
* would return false on an instance, then so will this function.
|
||||||
|
*
|
||||||
|
* @param value The value to check against the contained value.
|
||||||
|
*/
|
||||||
|
bool IsSignedImmediate(s64 value) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not the contained value matches the provided unsigned one.
|
||||||
|
*
|
||||||
|
* Note that this function will always return false if the contained
|
||||||
|
* value is not a a constant value. In other words, if IsImmediate()
|
||||||
|
* would return false on an instance, then so will this function.
|
||||||
|
*
|
||||||
|
* @param value The value to check against the contained value.
|
||||||
|
*/
|
||||||
|
bool IsUnsignedImmediate(u64 value) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether or not the contained constant value has all bits set.
|
* Determines whether or not the contained constant value has all bits set.
|
||||||
*
|
*
|
||||||
|
@ -82,6 +112,15 @@ public:
|
||||||
*/
|
*/
|
||||||
bool HasAllBitsSet() const;
|
bool HasAllBitsSet() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the current value contains a representation of zero.
|
||||||
|
*
|
||||||
|
* Note that this function will always return false if the contained
|
||||||
|
* value is not a a constant value. In other words, if IsImmediate()
|
||||||
|
* would return false on an instance, then so will this function.
|
||||||
|
*/
|
||||||
|
bool IsZero() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type;
|
Type type;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ void FoldAND(IR::Inst& inst, bool is_32_bit) {
|
||||||
} else {
|
} else {
|
||||||
inst.ReplaceUsesWith(IR::Value{result});
|
inst.ReplaceUsesWith(IR::Value{result});
|
||||||
}
|
}
|
||||||
} else if ((is_lhs_immediate && lhs.GetImmediateAsU64() == 0) || (is_rhs_immediate && rhs.GetImmediateAsU64() == 0)) {
|
} else if (lhs.IsZero() || rhs.IsZero()) {
|
||||||
if (is_32_bit) {
|
if (is_32_bit) {
|
||||||
inst.ReplaceUsesWith(IR::Value{u32{0}});
|
inst.ReplaceUsesWith(IR::Value{u32{0}});
|
||||||
} else {
|
} else {
|
||||||
|
@ -59,10 +59,7 @@ void FoldEOR(IR::Inst& inst, bool is_32_bit) {
|
||||||
const auto lhs = inst.GetArg(0);
|
const auto lhs = inst.GetArg(0);
|
||||||
const auto rhs = inst.GetArg(1);
|
const auto rhs = inst.GetArg(1);
|
||||||
|
|
||||||
const bool is_lhs_immediate = lhs.IsImmediate();
|
if (lhs.IsImmediate() && rhs.IsImmediate()) {
|
||||||
const bool is_rhs_immediate = rhs.IsImmediate();
|
|
||||||
|
|
||||||
if (is_lhs_immediate && is_rhs_immediate) {
|
|
||||||
const u64 result = lhs.GetImmediateAsU64() ^ rhs.GetImmediateAsU64();
|
const u64 result = lhs.GetImmediateAsU64() ^ rhs.GetImmediateAsU64();
|
||||||
|
|
||||||
if (is_32_bit) {
|
if (is_32_bit) {
|
||||||
|
@ -70,9 +67,9 @@ void FoldEOR(IR::Inst& inst, bool is_32_bit) {
|
||||||
} else {
|
} else {
|
||||||
inst.ReplaceUsesWith(IR::Value{result});
|
inst.ReplaceUsesWith(IR::Value{result});
|
||||||
}
|
}
|
||||||
} else if (is_lhs_immediate && lhs.GetImmediateAsU64() == 0) {
|
} else if (lhs.IsZero()) {
|
||||||
inst.ReplaceUsesWith(rhs);
|
inst.ReplaceUsesWith(rhs);
|
||||||
} else if (is_rhs_immediate && rhs.GetImmediateAsU64() == 0) {
|
} else if (rhs.IsZero()) {
|
||||||
inst.ReplaceUsesWith(lhs);
|
inst.ReplaceUsesWith(lhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,10 +99,7 @@ void FoldOR(IR::Inst& inst, bool is_32_bit) {
|
||||||
const auto lhs = inst.GetArg(0);
|
const auto lhs = inst.GetArg(0);
|
||||||
const auto rhs = inst.GetArg(1);
|
const auto rhs = inst.GetArg(1);
|
||||||
|
|
||||||
const bool is_lhs_immediate = lhs.IsImmediate();
|
if (lhs.IsImmediate() && rhs.IsImmediate()) {
|
||||||
const bool is_rhs_immediate = rhs.IsImmediate();
|
|
||||||
|
|
||||||
if (is_lhs_immediate && is_rhs_immediate) {
|
|
||||||
const u64 result = lhs.GetImmediateAsU64() | rhs.GetImmediateAsU64();
|
const u64 result = lhs.GetImmediateAsU64() | rhs.GetImmediateAsU64();
|
||||||
|
|
||||||
if (is_32_bit) {
|
if (is_32_bit) {
|
||||||
|
@ -113,9 +107,9 @@ void FoldOR(IR::Inst& inst, bool is_32_bit) {
|
||||||
} else {
|
} else {
|
||||||
inst.ReplaceUsesWith(IR::Value{result});
|
inst.ReplaceUsesWith(IR::Value{result});
|
||||||
}
|
}
|
||||||
} else if (is_lhs_immediate && lhs.GetImmediateAsU64() == 0) {
|
} else if (lhs.IsZero()) {
|
||||||
inst.ReplaceUsesWith(rhs);
|
inst.ReplaceUsesWith(rhs);
|
||||||
} else if (is_rhs_immediate && rhs.GetImmediateAsU64() == 0) {
|
} else if (rhs.IsZero()) {
|
||||||
inst.ReplaceUsesWith(lhs);
|
inst.ReplaceUsesWith(lhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue