A64: Implement FCVTZS, FCVTZU, UCVTF, SCVTF (vector, fixed-point), vector variant

This commit is contained in:
MerryMage 2018-09-19 19:47:28 +01:00
parent 48df9b9a7d
commit f9129db6fd
3 changed files with 66 additions and 5 deletions

View file

@ -1241,7 +1241,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
const size_t fbits = inst->GetArg(1).GetU8(); const size_t fbits = inst->GetArg(1).GetU8();
const auto rounding = static_cast<FP::RoundingMode>(inst->GetArg(2).GetU8()); const auto rounding = static_cast<FP::RoundingMode>(inst->GetArg(2).GetU8());
using fbits_list = mp::vllift<std::make_index_sequence<fsize>>; using fbits_list = mp::vllift<std::make_index_sequence<fsize + 1>>;
using rounding_list = mp::list< using rounding_list = mp::list<
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieEven>, std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieEven>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsPlusInfinity>, std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsPlusInfinity>,

View file

@ -801,8 +801,8 @@ INST(RSHRN, "RSHRN, RSHRN2", "0Q001
INST(SQSHRN_2, "SQSHRN, SQSHRN2", "0Q0011110IIIIiii100101nnnnnddddd") INST(SQSHRN_2, "SQSHRN, SQSHRN2", "0Q0011110IIIIiii100101nnnnnddddd")
INST(SQRSHRN_2, "SQRSHRN, SQRSHRN2", "0Q0011110IIIIiii100111nnnnnddddd") INST(SQRSHRN_2, "SQRSHRN, SQRSHRN2", "0Q0011110IIIIiii100111nnnnnddddd")
INST(SSHLL, "SSHLL, SSHLL2", "0Q0011110IIIIiii101001nnnnnddddd") INST(SSHLL, "SSHLL, SSHLL2", "0Q0011110IIIIiii101001nnnnnddddd")
//INST(SCVTF_fix_2, "SCVTF (vector, fixed-point)", "0Q0011110IIIIiii111001nnnnnddddd") INST(SCVTF_fix_2, "SCVTF (vector, fixed-point)", "0Q0011110IIIIiii111001nnnnnddddd")
//INST(FCVTZS_fix_2, "FCVTZS (vector, fixed-point)", "0Q0011110IIIIiii111111nnnnnddddd") INST(FCVTZS_fix_2, "FCVTZS (vector, fixed-point)", "0Q0011110IIIIiii111111nnnnnddddd")
INST(USHR_2, "USHR", "0Q1011110IIIIiii000001nnnnnddddd") INST(USHR_2, "USHR", "0Q1011110IIIIiii000001nnnnnddddd")
INST(USRA_2, "USRA", "0Q1011110IIIIiii000101nnnnnddddd") INST(USRA_2, "USRA", "0Q1011110IIIIiii000101nnnnnddddd")
INST(URSHR_2, "URSHR", "0Q1011110IIIIiii001001nnnnnddddd") INST(URSHR_2, "URSHR", "0Q1011110IIIIiii001001nnnnnddddd")
@ -816,8 +816,8 @@ INST(SQRSHRUN_2, "SQRSHRUN, SQRSHRUN2", "0Q101
INST(UQSHRN_2, "UQSHRN, UQSHRN2", "0Q1011110IIIIiii100101nnnnnddddd") INST(UQSHRN_2, "UQSHRN, UQSHRN2", "0Q1011110IIIIiii100101nnnnnddddd")
INST(UQRSHRN_2, "UQRSHRN, UQRSHRN2", "0Q1011110IIIIiii100111nnnnnddddd") INST(UQRSHRN_2, "UQRSHRN, UQRSHRN2", "0Q1011110IIIIiii100111nnnnnddddd")
INST(USHLL, "USHLL, USHLL2", "0Q1011110IIIIiii101001nnnnnddddd") INST(USHLL, "USHLL, USHLL2", "0Q1011110IIIIiii101001nnnnnddddd")
//INST(UCVTF_fix_2, "UCVTF (vector, fixed-point)", "0Q1011110IIIIiii111001nnnnnddddd") INST(UCVTF_fix_2, "UCVTF (vector, fixed-point)", "0Q1011110IIIIiii111001nnnnnddddd")
//INST(FCVTZU_fix_2, "FCVTZU (vector, fixed-point)", "0Q1011110IIIIiii111111nnnnnddddd") INST(FCVTZU_fix_2, "FCVTZU (vector, fixed-point)", "0Q1011110IIIIiii111111nnnnnddddd")
// Data Processing - FP and SIMD - SIMD vector x indexed element // Data Processing - FP and SIMD - SIMD vector x indexed element
INST(SMLAL_elt, "SMLAL, SMLAL2 (by element)", "0Q001111zzLMmmmm0010H0nnnnnddddd") INST(SMLAL_elt, "SMLAL, SMLAL2 (by element)", "0Q001111zzLMmmmm0010H0nnnnnddddd")

View file

@ -5,6 +5,7 @@
*/ */
#include "common/bit_util.h" #include "common/bit_util.h"
#include "common/fp/rounding_mode.h"
#include "frontend/A64/translate/impl/impl.h" #include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic::A64 { namespace Dynarmic::A64 {
@ -30,6 +31,11 @@ enum class Narrowing {
SaturateToSigned, SaturateToSigned,
}; };
enum class FloatConversionDirection {
FixedToFloat,
FloatToFixed,
};
IR::U128 PerformRoundingCorrection(TranslatorVisitor& v, size_t esize, u64 round_value, IR::U128 original, IR::U128 shifted) { IR::U128 PerformRoundingCorrection(TranslatorVisitor& v, size_t esize, u64 round_value, IR::U128 original, IR::U128 shifted) {
const IR::U128 round_const = v.ir.VectorBroadcast(esize, v.I(esize, round_value)); const IR::U128 round_const = v.ir.VectorBroadcast(esize, v.I(esize, round_value));
const IR::U128 round_correction = v.ir.VectorEqual(esize, v.ir.VectorAnd(original, round_const), round_const); const IR::U128 round_correction = v.ir.VectorEqual(esize, v.ir.VectorAnd(original, round_const), round_const);
@ -176,6 +182,45 @@ bool SaturatingShiftLeft(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb,
v.V(datasize, Vd, result); v.V(datasize, Vd, result);
return true; return true;
} }
bool ConvertFloat(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness signedness, FloatConversionDirection direction, FP::RoundingMode rounding_mode) {
if (immh == 0b0000) {
return v.DecodeError();
}
if (immh == 0b0001 || immh == 0b0010 || immh == 0b0011) {
return v.ReservedValue();
}
if (immh.Bit<3>() && !Q) {
return v.ReservedValue();
}
const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend());
const size_t datasize = Q ? 128 : 64;
const u8 fbits = static_cast<u8>(esize * 2) - concatenate(immh, immb).ZeroExtend<u8>();
const IR::U128 operand = v.V(datasize, Vn);
const IR::U128 result = [&] {
switch (direction) {
case FloatConversionDirection::FixedToFloat:
return signedness == Signedness::Signed
? v.ir.FPVectorFromSignedFixed(esize, operand, fbits, rounding_mode)
: v.ir.FPVectorFromUnsignedFixed(esize, operand, fbits, rounding_mode);
case FloatConversionDirection::FloatToFixed:
return signedness == Signedness::Signed
? v.ir.FPVectorToSignedFixed(esize, operand, fbits, rounding_mode)
: v.ir.FPVectorToUnsignedFixed(esize, operand, fbits, rounding_mode);
}
UNREACHABLE();
return IR::U128{};
}();
v.V(datasize, Vd, result);
return true;
}
} // Anonymous namespace } // Anonymous namespace
bool TranslatorVisitor::SSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
@ -329,4 +374,20 @@ bool TranslatorVisitor::SLI_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd)
return true; return true;
} }
bool TranslatorVisitor::SCVTF_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
return ConvertFloat(*this, Q, immh, immb, Vn, Vd, Signedness::Signed, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode());
}
bool TranslatorVisitor::UCVTF_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
return ConvertFloat(*this, Q, immh, immb, Vn, Vd, Signedness::Unsigned, FloatConversionDirection::FixedToFloat, ir.current_location->FPCR().RMode());
}
bool TranslatorVisitor::FCVTZS_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
return ConvertFloat(*this, Q, immh, immb, Vn, Vd, Signedness::Signed, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero);
}
bool TranslatorVisitor::FCVTZU_fix_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
return ConvertFloat(*this, Q, immh, immb, Vn, Vd, Signedness::Unsigned, FloatConversionDirection::FloatToFixed, FP::RoundingMode::TowardsZero);
}
} // namespace Dynarmic::A64 } // namespace Dynarmic::A64