A64: Implement FMOV (scalar, immediate)
This commit is contained in:
parent
a07c05ea51
commit
4be55b8b84
7 changed files with 78 additions and 1 deletions
|
@ -75,6 +75,7 @@ add_library(dynarmic
|
||||||
frontend/A64/translate/impl/data_processing_shift.cpp
|
frontend/A64/translate/impl/data_processing_shift.cpp
|
||||||
frontend/A64/translate/impl/exception_generating.cpp
|
frontend/A64/translate/impl/exception_generating.cpp
|
||||||
frontend/A64/translate/impl/floating_point_compare.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/floating_point_data_processing_two_register.cpp
|
||||||
frontend/A64/translate/impl/impl.cpp
|
frontend/A64/translate/impl/impl.cpp
|
||||||
frontend/A64/translate/impl/impl.h
|
frontend/A64/translate/impl/impl.h
|
||||||
|
|
|
@ -933,7 +933,7 @@ INST(FCMP_float, "FCMP", "00011
|
||||||
INST(FCMPE_float, "FCMPE", "00011110yy1mmmmm001000nnnnn1o000")
|
INST(FCMPE_float, "FCMPE", "00011110yy1mmmmm001000nnnnn1o000")
|
||||||
|
|
||||||
// Data Processing - FP and SIMD - Floating point immediate
|
// 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
|
// Data Processing - FP and SIMD - Floating point conditional compare
|
||||||
//INST(FCCMP_float, "FCCMP", "00011110yy1mmmmmcccc01nnnnn0ffff")
|
//INST(FCCMP_float, "FCCMP", "00011110yy1mmmmmcccc01nnnnn0ffff")
|
||||||
|
|
|
@ -44,6 +44,12 @@ public:
|
||||||
return Common::Bit<bit>(value);
|
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 {
|
bool operator==(const Imm<bit_size>& other) const {
|
||||||
return value == other.value;
|
return value == other.value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
@ -18,6 +18,10 @@ U8 IREmitter::Imm8(u8 imm8) {
|
||||||
return U8(Value(imm8));
|
return U8(Value(imm8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U16 IREmitter::Imm16(u16 imm16) {
|
||||||
|
return U16(Value(imm16));
|
||||||
|
}
|
||||||
|
|
||||||
U32 IREmitter::Imm32(u32 imm32) {
|
U32 IREmitter::Imm32(u32 imm32) {
|
||||||
return U32(Value(imm32));
|
return U32(Value(imm32));
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
|
|
||||||
U1 Imm1(bool value);
|
U1 Imm1(bool value);
|
||||||
U8 Imm8(u8 value);
|
U8 Imm8(u8 value);
|
||||||
|
U16 Imm16(u16 value);
|
||||||
U32 Imm32(u32 value);
|
U32 Imm32(u32 value);
|
||||||
U64 Imm64(u64 value);
|
U64 Imm64(u64 value);
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ static std::vector<InstructionGenerator> instruction_generators = []{
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<InstructionGenerator> result;
|
std::vector<InstructionGenerator> result;
|
||||||
|
|
||||||
for (const auto& [fn, bitstring] : list) {
|
for (const auto& [fn, bitstring] : list) {
|
||||||
if (std::strcmp(fn, "UnallocatedEncoding") == 0) {
|
if (std::strcmp(fn, "UnallocatedEncoding") == 0) {
|
||||||
InstructionGenerator::AddInvalidInstruction(bitstring);
|
InstructionGenerator::AddInvalidInstruction(bitstring);
|
||||||
|
@ -46,6 +47,11 @@ static std::vector<InstructionGenerator> instruction_generators = []{
|
||||||
}
|
}
|
||||||
result.emplace_back(InstructionGenerator{bitstring});
|
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;
|
return result;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue