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 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>,
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue