diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c149f02..d37aebef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -76,6 +76,7 @@ add_library(dynarmic frontend/A64/types.h frontend/decoder/decoder_detail.h frontend/decoder/matcher.h + frontend/imm.cpp frontend/imm.h frontend/ir/basic_block.cpp frontend/ir/basic_block.h diff --git a/src/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp b/src/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp index a309474f..4922a9aa 100644 --- a/src/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp +++ b/src/frontend/A32/translate/impl/asimd_one_reg_modified_immediate.cpp @@ -13,59 +13,6 @@ namespace { ExtReg ToExtRegD(size_t base, bool bit) { return ExtReg::D0 + (base + (bit ? 16 : 0)); } - -u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8) { - switch (cmode.Bits<1, 3>()) { - case 0b000: - return Common::Replicate(imm8.ZeroExtend(), 32); - case 0b001: - return Common::Replicate(imm8.ZeroExtend() << 8, 32); - case 0b010: - return Common::Replicate(imm8.ZeroExtend() << 16, 32); - case 0b011: - return Common::Replicate(imm8.ZeroExtend() << 24, 32); - case 0b100: - return Common::Replicate(imm8.ZeroExtend(), 16); - case 0b101: - return Common::Replicate(imm8.ZeroExtend() << 8, 16); - case 0b110: - if (!cmode.Bit<0>()) { - return Common::Replicate((imm8.ZeroExtend() << 8) | Common::Ones(8), 32); - } - return Common::Replicate((imm8.ZeroExtend() << 16) | Common::Ones(16), 32); - case 0b111: - if (!cmode.Bit<0>() && !op) { - return Common::Replicate(imm8.ZeroExtend(), 8); - } - if (!cmode.Bit<0>() && op) { - u64 result = 0; - result |= imm8.Bit<0>() ? Common::Ones(8) << (0 * 8) : 0; - result |= imm8.Bit<1>() ? Common::Ones(8) << (1 * 8) : 0; - result |= imm8.Bit<2>() ? Common::Ones(8) << (2 * 8) : 0; - result |= imm8.Bit<3>() ? Common::Ones(8) << (3 * 8) : 0; - result |= imm8.Bit<4>() ? Common::Ones(8) << (4 * 8) : 0; - result |= imm8.Bit<5>() ? Common::Ones(8) << (5 * 8) : 0; - result |= imm8.Bit<6>() ? Common::Ones(8) << (6 * 8) : 0; - result |= imm8.Bit<7>() ? Common::Ones(8) << (7 * 8) : 0; - return result; - } - if (cmode.Bit<0>() && !op) { - u64 result = 0; - result |= imm8.Bit<7>() ? 0x80000000 : 0; - result |= imm8.Bit<6>() ? 0x3E000000 : 0x40000000; - result |= imm8.Bits<0, 5, u64>() << 19; - return Common::Replicate(result, 32); - } - if (cmode.Bit<0>() && op) { - u64 result = 0; - result |= imm8.Bit<7>() ? 0x80000000'00000000 : 0; - result |= imm8.Bit<6>() ? 0x3FC00000'00000000 : 0x40000000'00000000; - result |= imm8.Bits<0, 5, u64>() << 48; - return result; - } - } - UNREACHABLE(); -} } // Anonymous namespace bool ArmTranslatorVisitor::asimd_VMOV_imm(Imm<1> a, bool D, Imm<1> b, Imm<1> c, Imm<1> d, size_t Vd, diff --git a/src/frontend/A64/translate/impl/impl.cpp b/src/frontend/A64/translate/impl/impl.cpp index 65d464bb..b13b3b07 100644 --- a/src/frontend/A64/translate/impl/impl.cpp +++ b/src/frontend/A64/translate/impl/impl.cpp @@ -61,59 +61,6 @@ std::optional TranslatorVisitor::DecodeBitMasks(boo return BitMasks{wmask, tmask}; } -u64 TranslatorVisitor::AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8) { - switch (cmode.Bits<1, 3>()) { - case 0b000: - return Common::Replicate(imm8.ZeroExtend(), 32); - case 0b001: - return Common::Replicate(imm8.ZeroExtend() << 8, 32); - case 0b010: - return Common::Replicate(imm8.ZeroExtend() << 16, 32); - case 0b011: - return Common::Replicate(imm8.ZeroExtend() << 24, 32); - case 0b100: - return Common::Replicate(imm8.ZeroExtend(), 16); - case 0b101: - return Common::Replicate(imm8.ZeroExtend() << 8, 16); - case 0b110: - if (!cmode.Bit<0>()) { - return Common::Replicate((imm8.ZeroExtend() << 8) | Common::Ones(8), 32); - } - return Common::Replicate((imm8.ZeroExtend() << 16) | Common::Ones(16), 32); - case 0b111: - if (!cmode.Bit<0>() && !op) { - return Common::Replicate(imm8.ZeroExtend(), 8); - } - if (!cmode.Bit<0>() && op) { - u64 result = 0; - result |= imm8.Bit<0>() ? Common::Ones(8) << (0 * 8) : 0; - result |= imm8.Bit<1>() ? Common::Ones(8) << (1 * 8) : 0; - result |= imm8.Bit<2>() ? Common::Ones(8) << (2 * 8) : 0; - result |= imm8.Bit<3>() ? Common::Ones(8) << (3 * 8) : 0; - result |= imm8.Bit<4>() ? Common::Ones(8) << (4 * 8) : 0; - result |= imm8.Bit<5>() ? Common::Ones(8) << (5 * 8) : 0; - result |= imm8.Bit<6>() ? Common::Ones(8) << (6 * 8) : 0; - result |= imm8.Bit<7>() ? Common::Ones(8) << (7 * 8) : 0; - return result; - } - if (cmode.Bit<0>() && !op) { - u64 result = 0; - result |= imm8.Bit<7>() ? 0x80000000 : 0; - result |= imm8.Bit<6>() ? 0x3E000000 : 0x40000000; - result |= imm8.Bits<0, 5, u64>() << 19; - return Common::Replicate(result, 32); - } - if (cmode.Bit<0>() && op) { - u64 result = 0; - result |= imm8.Bit<7>() ? 0x80000000'00000000 : 0; - result |= imm8.Bit<6>() ? 0x3FC00000'00000000 : 0x40000000'00000000; - result |= imm8.Bits<0, 5, u64>() << 48; - return result; - } - } - UNREACHABLE(); -} - IR::UAny TranslatorVisitor::I(size_t bitsize, u64 value) { switch (bitsize) { case 8: diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index c199bbd1..d6ed6a59 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -35,7 +35,6 @@ struct TranslatorVisitor final { }; static std::optional DecodeBitMasks(bool immN, Imm<6> imms, Imm<6> immr, bool immediate); - static u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8); IR::UAny I(size_t bitsize, u64 value); IR::UAny X(size_t bitsize, Reg reg); diff --git a/src/frontend/imm.cpp b/src/frontend/imm.cpp new file mode 100644 index 00000000..282ff911 --- /dev/null +++ b/src/frontend/imm.cpp @@ -0,0 +1,66 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "common/assert.h" +#include "common/bit_util.h" +#include "common/common_types.h" +#include "frontend/imm.h" + +namespace Dynarmic { + +u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8) { + switch (cmode.Bits<1, 3>()) { + case 0b000: + return Common::Replicate(imm8.ZeroExtend(), 32); + case 0b001: + return Common::Replicate(imm8.ZeroExtend() << 8, 32); + case 0b010: + return Common::Replicate(imm8.ZeroExtend() << 16, 32); + case 0b011: + return Common::Replicate(imm8.ZeroExtend() << 24, 32); + case 0b100: + return Common::Replicate(imm8.ZeroExtend(), 16); + case 0b101: + return Common::Replicate(imm8.ZeroExtend() << 8, 16); + case 0b110: + if (!cmode.Bit<0>()) { + return Common::Replicate((imm8.ZeroExtend() << 8) | Common::Ones(8), 32); + } + return Common::Replicate((imm8.ZeroExtend() << 16) | Common::Ones(16), 32); + case 0b111: + if (!cmode.Bit<0>() && !op) { + return Common::Replicate(imm8.ZeroExtend(), 8); + } + if (!cmode.Bit<0>() && op) { + u64 result = 0; + result |= imm8.Bit<0>() ? Common::Ones(8) << (0 * 8) : 0; + result |= imm8.Bit<1>() ? Common::Ones(8) << (1 * 8) : 0; + result |= imm8.Bit<2>() ? Common::Ones(8) << (2 * 8) : 0; + result |= imm8.Bit<3>() ? Common::Ones(8) << (3 * 8) : 0; + result |= imm8.Bit<4>() ? Common::Ones(8) << (4 * 8) : 0; + result |= imm8.Bit<5>() ? Common::Ones(8) << (5 * 8) : 0; + result |= imm8.Bit<6>() ? Common::Ones(8) << (6 * 8) : 0; + result |= imm8.Bit<7>() ? Common::Ones(8) << (7 * 8) : 0; + return result; + } + if (cmode.Bit<0>() && !op) { + u64 result = 0; + result |= imm8.Bit<7>() ? 0x80000000 : 0; + result |= imm8.Bit<6>() ? 0x3E000000 : 0x40000000; + result |= imm8.Bits<0, 5, u64>() << 19; + return Common::Replicate(result, 32); + } + if (cmode.Bit<0>() && op) { + u64 result = 0; + result |= imm8.Bit<7>() ? 0x80000000'00000000 : 0; + result |= imm8.Bit<6>() ? 0x3FC00000'00000000 : 0x40000000'00000000; + result |= imm8.Bits<0, 5, u64>() << 48; + return result; + } + } + UNREACHABLE(); +} + +} // namespace Dynarmic diff --git a/src/frontend/imm.h b/src/frontend/imm.h index a0e666b4..cde09902 100644 --- a/src/frontend/imm.h +++ b/src/frontend/imm.h @@ -157,4 +157,7 @@ auto concatenate(Imm first, Imm ...rest) { } } +/// Expands an Advanced SIMD modified immediate. +u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8); + } // namespace Dynarmic