/* 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::A64 { /** * Imm represents an immediate value in an 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==(const Imm& other) const { return value == other.value; } bool operator!=(const 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, const Imm& b) { return Imm{a} == b; } template bool operator==(const Imm& a, u32 b) { return Imm{b} == a; } template bool operator!=(u32 a, const Imm& b) { return Imm{a} != b; } template bool operator!=(const Imm& a, u32 b) { return Imm{b} != a; } /** * 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::A64