A64: Implement FCVTZS, FCVTZU, UCVTF, SCVTF (vector, fixed-point), vector variant
This commit is contained in:
parent
48df9b9a7d
commit
f9129db6fd
3 changed files with 66 additions and 5 deletions
|
@ -1241,7 +1241,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
const size_t fbits = inst->GetArg(1).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<
|
||||
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieEven>,
|
||||
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsPlusInfinity>,
|
||||
|
|
|
@ -801,8 +801,8 @@ INST(RSHRN, "RSHRN, RSHRN2", "0Q001
|
|||
INST(SQSHRN_2, "SQSHRN, SQSHRN2", "0Q0011110IIIIiii100101nnnnnddddd")
|
||||
INST(SQRSHRN_2, "SQRSHRN, SQRSHRN2", "0Q0011110IIIIiii100111nnnnnddddd")
|
||||
INST(SSHLL, "SSHLL, SSHLL2", "0Q0011110IIIIiii101001nnnnnddddd")
|
||||
//INST(SCVTF_fix_2, "SCVTF (vector, fixed-point)", "0Q0011110IIIIiii111001nnnnnddddd")
|
||||
//INST(FCVTZS_fix_2, "FCVTZS (vector, fixed-point)", "0Q0011110IIIIiii111111nnnnnddddd")
|
||||
INST(SCVTF_fix_2, "SCVTF (vector, fixed-point)", "0Q0011110IIIIiii111001nnnnnddddd")
|
||||
INST(FCVTZS_fix_2, "FCVTZS (vector, fixed-point)", "0Q0011110IIIIiii111111nnnnnddddd")
|
||||
INST(USHR_2, "USHR", "0Q1011110IIIIiii000001nnnnnddddd")
|
||||
INST(USRA_2, "USRA", "0Q1011110IIIIiii000101nnnnnddddd")
|
||||
INST(URSHR_2, "URSHR", "0Q1011110IIIIiii001001nnnnnddddd")
|
||||
|
@ -816,8 +816,8 @@ INST(SQRSHRUN_2, "SQRSHRUN, SQRSHRUN2", "0Q101
|
|||
INST(UQSHRN_2, "UQSHRN, UQSHRN2", "0Q1011110IIIIiii100101nnnnnddddd")
|
||||
INST(UQRSHRN_2, "UQRSHRN, UQRSHRN2", "0Q1011110IIIIiii100111nnnnnddddd")
|
||||
INST(USHLL, "USHLL, USHLL2", "0Q1011110IIIIiii101001nnnnnddddd")
|
||||
//INST(UCVTF_fix_2, "UCVTF (vector, fixed-point)", "0Q1011110IIIIiii111001nnnnnddddd")
|
||||
//INST(FCVTZU_fix_2, "FCVTZU (vector, fixed-point)", "0Q1011110IIIIiii111111nnnnnddddd")
|
||||
INST(UCVTF_fix_2, "UCVTF (vector, fixed-point)", "0Q1011110IIIIiii111001nnnnnddddd")
|
||||
INST(FCVTZU_fix_2, "FCVTZU (vector, fixed-point)", "0Q1011110IIIIiii111111nnnnnddddd")
|
||||
|
||||
// Data Processing - FP and SIMD - SIMD vector x indexed element
|
||||
INST(SMLAL_elt, "SMLAL, SMLAL2 (by element)", "0Q001111zzLMmmmm0010H0nnnnnddddd")
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include "common/bit_util.h"
|
||||
#include "common/fp/rounding_mode.h"
|
||||
#include "frontend/A64/translate/impl/impl.h"
|
||||
|
||||
namespace Dynarmic::A64 {
|
||||
|
@ -30,6 +31,11 @@ enum class Narrowing {
|
|||
SaturateToSigned,
|
||||
};
|
||||
|
||||
enum class FloatConversionDirection {
|
||||
FixedToFloat,
|
||||
FloatToFixed,
|
||||
};
|
||||
|
||||
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_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);
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue