A64: Implement FMOV (scalar, immediate)

This commit is contained in:
MerryMage 2018-02-03 00:52:48 +00:00
parent a07c05ea51
commit 4be55b8b84
7 changed files with 78 additions and 1 deletions

View file

@ -75,6 +75,7 @@ add_library(dynarmic
frontend/A64/translate/impl/data_processing_shift.cpp
frontend/A64/translate/impl/exception_generating.cpp
frontend/A64/translate/impl/floating_point_compare.cpp
frontend/A64/translate/impl/floating_point_data_processing_one_register.cpp
frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp
frontend/A64/translate/impl/impl.cpp
frontend/A64/translate/impl/impl.h

View file

@ -933,7 +933,7 @@ INST(FCMP_float, "FCMP", "00011
INST(FCMPE_float, "FCMPE", "00011110yy1mmmmm001000nnnnn1o000")
// Data Processing - FP and SIMD - Floating point immediate
//INST(FMOV_float_imm, "FMOV (scalar, immediate)", "00011110yy1iiiiiiii10000000ddddd")
INST(FMOV_float_imm, "FMOV (scalar, immediate)", "00011110yy1iiiiiiii10000000ddddd")
// Data Processing - FP and SIMD - Floating point conditional compare
//INST(FCCMP_float, "FCCMP", "00011110yy1mmmmmcccc01nnnnn0ffff")

View file

@ -44,6 +44,12 @@ public:
return Common::Bit<bit>(value);
}
template <size_t begin_bit, size_t end_bit, typename T = u32>
T Bits() const {
static_assert(Common::BitSize<T>() >= end_bit - begin_bit + 1);
return static_cast<T>(Common::Bits<begin_bit, end_bit>(value));
}
bool operator==(const Imm<bit_size>& other) const {
return value == other.value;
}

View file

@ -0,0 +1,59 @@
/* 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.
*/
#include <boost/optional.hpp>
#include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic::A64 {
static boost::optional<size_t> GetDataSize(Imm<2> type) {
switch (type.ZeroExtend()) {
case 0b00:
return 32;
case 0b01:
return 64;
case 0b11:
return 16;
}
return boost::none;
}
bool TranslatorVisitor::FMOV_float_imm(Imm<2> type, Imm<8> imm8, Vec Vd) {
boost::optional<size_t> datasize = GetDataSize(type);
if (!datasize) {
return UnallocatedEncoding();
}
IR::UAny result = [&]() -> IR::UAny {
switch (*datasize) {
case 16: {
const u16 sign = imm8.Bit<7>() ? 1 : 0;
const u16 exp = (imm8.Bit<6>() ? 0b0'1100 : 0b1'0000) | imm8.Bits<4, 5, u16>();
const u16 fract = imm8.Bits<0, 3, u16>() << 6;
return ir.Imm16((sign << 15) | (exp << 10) | fract);
}
case 32: {
const u32 sign = imm8.Bit<7>() ? 1 : 0;
const u32 exp = (imm8.Bit<6>() ? 0b0111'1100 : 0b1000'0000) | imm8.Bits<4, 5, u32>();
const u32 fract = imm8.Bits<0, 3, u32>() << 19;
return ir.Imm32((sign << 31) | (exp << 23) | fract);
}
case 64:
default: {
const u64 sign = imm8.Bit<7>() ? 1 : 0;
const u64 exp = (imm8.Bit<6>() ? 0b011'1111'1100 : 0b100'0000'0000) | imm8.Bits<4, 5, u64>();
const u64 fract = imm8.Bits<0, 3, u64>() << 48;
return ir.Imm64((sign << 63) | (exp << 52) | fract);
}
}
}();
V_scalar(*datasize, Vd, result);
return true;
}
} // namespace Dynarmic::A64

View file

@ -18,6 +18,10 @@ U8 IREmitter::Imm8(u8 imm8) {
return U8(Value(imm8));
}
U16 IREmitter::Imm16(u16 imm16) {
return U16(Value(imm16));
}
U32 IREmitter::Imm32(u32 imm32) {
return U32(Value(imm32));
}

View file

@ -61,6 +61,7 @@ public:
U1 Imm1(bool value);
U8 Imm8(u8 value);
U16 Imm16(u16 value);
U32 Imm32(u32 value);
U64 Imm64(u64 value);

View file

@ -39,6 +39,7 @@ static std::vector<InstructionGenerator> instruction_generators = []{
};
std::vector<InstructionGenerator> result;
for (const auto& [fn, bitstring] : list) {
if (std::strcmp(fn, "UnallocatedEncoding") == 0) {
InstructionGenerator::AddInvalidInstruction(bitstring);
@ -46,6 +47,11 @@ static std::vector<InstructionGenerator> instruction_generators = []{
}
result.emplace_back(InstructionGenerator{bitstring});
}
// Manually added exceptions:
// FMOV_float_imm for half-precision floats (QEMU doesn't have half-precision support yet).
InstructionGenerator::AddInvalidInstruction("00011110111iiiiiiii10000000ddddd");
return result;
}();