From 41ba9fd7bcdde2f36df5d8aa482cdb53f483e882 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 28 Sep 2018 14:46:38 -0400 Subject: [PATCH] value: Move ImmediateToU64() to be a part of Value's interface This'll make it slightly nicer to do basic constant folding for 32-bit and 64-bit variants of the same IR opcode type. By that, I mean it's possible to inspect immediate values without a bunch of conditional checks beforehand to verify that it's possible to call GetU32() or GetU64, etc. --- src/backend/x64/reg_alloc.cpp | 40 ++++++++++------------------------- src/frontend/ir/value.cpp | 19 +++++++++++++++++ src/frontend/ir/value.h | 8 +++++++ 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/backend/x64/reg_alloc.cpp b/src/backend/x64/reg_alloc.cpp index 4bca5730..a6dd72f9 100644 --- a/src/backend/x64/reg_alloc.cpp +++ b/src/backend/x64/reg_alloc.cpp @@ -26,23 +26,6 @@ namespace Dynarmic::BackendX64 { } \ }() -static u64 ImmediateToU64(const IR::Value& imm) { - switch (imm.GetType()) { - case IR::Type::U1: - return u64(imm.GetU1()); - case IR::Type::U8: - return u64(imm.GetU8()); - case IR::Type::U16: - return u64(imm.GetU16()); - case IR::Type::U32: - return u64(imm.GetU32()); - case IR::Type::U64: - return u64(imm.GetU64()); - default: - ASSERT_MSG(false, "This should never happen."); - } -} - static bool CanExchange(HostLoc a, HostLoc b) { return HostLocIsGPR(a) && HostLocIsGPR(b); } @@ -179,14 +162,14 @@ bool Argument::IsVoid() const { bool Argument::FitsInImmediateU32() const { if (!IsImmediate()) return false; - u64 imm = ImmediateToU64(value); + const u64 imm = value.GetImmediateAsU64(); return imm < 0x100000000; } bool Argument::FitsInImmediateS32() const { if (!IsImmediate()) return false; - s64 imm = static_cast(ImmediateToU64(value)); + const s64 imm = static_cast(value.GetImmediateAsU64()); return -s64(0x80000000) <= imm && imm <= s64(0x7FFFFFFF); } @@ -195,31 +178,30 @@ bool Argument::GetImmediateU1() const { } u8 Argument::GetImmediateU8() const { - u64 imm = ImmediateToU64(value); + const u64 imm = value.GetImmediateAsU64(); ASSERT(imm < 0x100); return u8(imm); } u16 Argument::GetImmediateU16() const { - u64 imm = ImmediateToU64(value); + const u64 imm = value.GetImmediateAsU64(); ASSERT(imm < 0x10000); return u16(imm); } u32 Argument::GetImmediateU32() const { - u64 imm = ImmediateToU64(value); + const u64 imm = value.GetImmediateAsU64(); ASSERT(imm < 0x100000000); return u32(imm); } u64 Argument::GetImmediateS32() const { ASSERT(FitsInImmediateS32()); - u64 imm = ImmediateToU64(value); - return imm; + return value.GetImmediateAsU64(); } u64 Argument::GetImmediateU64() const { - return ImmediateToU64(value); + return value.GetImmediateAsU64(); } IR::Cond Argument::GetImmediateCond() const { @@ -502,8 +484,8 @@ HostLoc RegAlloc::LoadImmediate(IR::Value imm, HostLoc host_loc) { ASSERT_MSG(imm.IsImmediate(), "imm is not an immediate"); if (HostLocIsGPR(host_loc)) { - Xbyak::Reg64 reg = HostLocToReg64(host_loc); - u64 imm_value = ImmediateToU64(imm); + const Xbyak::Reg64 reg = HostLocToReg64(host_loc); + const u64 imm_value = imm.GetImmediateAsU64(); if (imm_value == 0) code.xor_(reg.cvt32(), reg.cvt32()); else @@ -512,8 +494,8 @@ HostLoc RegAlloc::LoadImmediate(IR::Value imm, HostLoc host_loc) { } if (HostLocIsXMM(host_loc)) { - Xbyak::Xmm reg = HostLocToXmm(host_loc); - u64 imm_value = ImmediateToU64(imm); + const Xbyak::Xmm reg = HostLocToXmm(host_loc); + const u64 imm_value = imm.GetImmediateAsU64(); if (imm_value == 0) MAYBE_AVX(xorps, reg, reg); else diff --git a/src/frontend/ir/value.cpp b/src/frontend/ir/value.cpp index f944646a..d5ba2c62 100644 --- a/src/frontend/ir/value.cpp +++ b/src/frontend/ir/value.cpp @@ -155,4 +155,23 @@ Cond Value::GetCond() const { return inner.imm_cond; } +u64 Value::GetImmediateAsU64() const { + ASSERT(IsImmediate()); + + switch (GetType()) { + case IR::Type::U1: + return u64(GetU1()); + case IR::Type::U8: + return u64(GetU8()); + case IR::Type::U16: + return u64(GetU16()); + case IR::Type::U32: + return u64(GetU32()); + case IR::Type::U64: + return u64(GetU64()); + default: + ASSERT_MSG(false, "GetImmediateAsU64 called on an incompatible Value type."); + } +} + } // namespace Dynarmic::IR diff --git a/src/frontend/ir/value.h b/src/frontend/ir/value.h index 22b8b977..4984ebdd 100644 --- a/src/frontend/ir/value.h +++ b/src/frontend/ir/value.h @@ -66,6 +66,14 @@ public: CoprocessorInfo GetCoprocInfo() const; Cond GetCond() const; + /** + * Retrieves the immediate of a Value instance. + * + * @pre The value contains either a U1, U8, U16, U32, or U64 value. + * Breaking this precondition will cause an assertion to be invoked. + */ + u64 GetImmediateAsU64() const; + private: Type type;