From 8ab7d8175c62d6f5242a64d1b0fdbc5f534638e4 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Tue, 6 Feb 2018 23:04:23 +0000 Subject: [PATCH] impl: Add AdvSIMDExpandImm --- src/frontend/A64/translate/impl/impl.cpp | 54 ++++++++++++++++++++++++ src/frontend/A64/translate/impl/impl.h | 1 + 2 files changed, 55 insertions(+) diff --git a/src/frontend/A64/translate/impl/impl.cpp b/src/frontend/A64/translate/impl/impl.cpp index 68a9e859..973ed45b 100644 --- a/src/frontend/A64/translate/impl/impl.cpp +++ b/src/frontend/A64/translate/impl/impl.cpp @@ -56,6 +56,60 @@ boost::optional TranslatorVisitor::DecodeBitMasks(b 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(); + return 0; +} + IR::U32U64 TranslatorVisitor::I(size_t bitsize, u64 value) { switch (bitsize) { case 32: diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index 1f1e8371..a3159e44 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -40,6 +40,7 @@ struct TranslatorVisitor final { }; boost::optional DecodeBitMasks(bool N, Imm<6> immr, Imm<6> imms, bool immediate); + u64 AdvSIMDExpandImm(bool op, Imm<4> cmode, Imm<8> imm8); IR::U32U64 I(size_t bitsize, u64 value); IR::UAny X(size_t bitsize, Reg reg);