/* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * This software may be used and distributed according to the terms of the GNU * General Public License version 2 or any later version. */ #pragma once #include "common/assert.h" #include "common/bit_util.h" #include "common/common_types.h" #include "common/math_util.h" namespace Dynarmic { /** * Imm represents an immediate value in an AArch32/AArch64 instruction. * Imm is used during translation as a typesafe way of passing around immediates of fixed sizes. */ template class Imm { public: static constexpr size_t bit_size = bit_size_; explicit Imm(u32 value) : value(value) { ASSERT_MSG((Common::Bits<0, bit_size-1>(value) == value), "More bits in value than expected"); } template T ZeroExtend() const { static_assert(Common::BitSize() >= bit_size); return static_cast(value); } template T SignExtend() const { static_assert(Common::BitSize() >= bit_size); return Common::SignExtend(value); } template bool Bit() const { static_assert(bit < bit_size); return Common::Bit(value); } template T Bits() const { static_assert(begin_bit <= end_bit && end_bit < bit_size); static_assert(Common::BitSize() >= end_bit - begin_bit + 1); return static_cast(Common::Bits(value)); } bool operator==(Imm other) const { return value == other.value; } bool operator!=(Imm other) const { return !operator==(other); } bool operator<(Imm other) const { return value < other.value; } bool operator<=(Imm other) const { return value <= other.value; } bool operator>(Imm other) const { return value > other.value; } bool operator>=(Imm other) const { return value >= other.value; } private: static_assert(bit_size != 0, "Cannot have a zero-sized immediate"); static_assert(bit_size <= 32, "Cannot have an immediate larger than the instruction size"); u32 value; }; template bool operator==(u32 a, Imm b) { return Imm{a} == b; } template bool operator==(Imm a, u32 b) { return Imm{b} == a; } template bool operator!=(u32 a, Imm b) { return !operator==(a, b); } template bool operator!=(Imm a, u32 b) { return !operator==(a, b); } template bool operator<(u32 a, Imm b) { return Imm{a} < b; } template bool operator<(Imm a, u32 b) { return a < Imm{b}; } template bool operator<=(u32 a, Imm b) { return !operator<(b, a); } template bool operator<=(Imm a, u32 b) { return !operator<(b, a); } template bool operator>(u32 a, Imm b) { return operator<(b, a); } template bool operator>(Imm a, u32 b) { return operator<(b, a); } template bool operator>=(u32 a, Imm b) { return !operator<(a, b); } template bool operator>=(Imm a, u32 b) { return !operator<(a, b); } /** * Concatentate immediates together. * Left to right corresponds to most significant imm to least significant imm. * This is equivalent to a:b:...:z in ASL. */ template auto concatenate(Imm first, Imm ...rest) { if constexpr (sizeof...(rest) == 0) { return first; } else { const auto concat_rest = concatenate(rest...); const u32 value = (first.ZeroExtend() << concat_rest.bit_size) | concat_rest.ZeroExtend(); return Imm{value}; } } } // namespace Dynarmic