simd_scalar_shift_by_immediate: Implement FCVT{ZS, ZU} (vector, fixed-point)'s scalar double/single-precision variant
This commit is contained in:
parent
91abf87169
commit
af3e23b224
2 changed files with 55 additions and 9 deletions
|
@ -477,7 +477,7 @@ INST(SHL_1, "SHL", "01011
|
|||
//INST(SQSHRN_1, "SQSHRN, SQSHRN2", "010111110IIIIiii100101nnnnnddddd")
|
||||
//INST(SQRSHRN_1, "SQRSHRN, SQRSHRN2", "010111110IIIIiii100111nnnnnddddd")
|
||||
//INST(SCVTF_fix_1, "SCVTF (vector, fixed-point)", "010111110IIIIiii111001nnnnnddddd")
|
||||
//INST(FCVTZS_fix_1, "FCVTZS (vector, fixed-point)", "010111110IIIIiii111111nnnnnddddd")
|
||||
INST(FCVTZS_fix_1, "FCVTZS (vector, fixed-point)", "010111110IIIIiii111111nnnnnddddd")
|
||||
INST(USHR_1, "USHR", "011111110IIIIiii000001nnnnnddddd")
|
||||
INST(USRA_1, "USRA", "011111110IIIIiii000101nnnnnddddd")
|
||||
INST(URSHR_1, "URSHR", "011111110IIIIiii001001nnnnnddddd")
|
||||
|
@ -491,7 +491,7 @@ INST(SLI_1, "SLI", "01111
|
|||
//INST(UQSHRN_1, "UQSHRN, UQSHRN2", "011111110IIIIiii100101nnnnnddddd")
|
||||
//INST(UQRSHRN_1, "UQRSHRN, UQRSHRN2", "011111110IIIIiii100111nnnnnddddd")
|
||||
//INST(UCVTF_fix_1, "UCVTF (vector, fixed-point)", "011111110IIIIiii111001nnnnnddddd")
|
||||
//INST(FCVTZU_fix_1, "FCVTZU (vector, fixed-point)", "011111110IIIIiii111111nnnnnddddd")
|
||||
INST(FCVTZU_fix_1, "FCVTZU (vector, fixed-point)", "011111110IIIIiii111111nnnnnddddd")
|
||||
|
||||
// Data Processing - FP and SIMD - SIMD Scalar x indexed element
|
||||
//INST(SQDMLAL_elt_1, "SQDMLAL, SQDMLAL2 (by element)", "01011111zzLMmmmm0011H0nnnnnddddd")
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "frontend/A64/translate/impl/impl.h"
|
||||
|
||||
namespace Dynarmic::A64 {
|
||||
|
||||
namespace {
|
||||
enum class ShiftExtraBehavior {
|
||||
None,
|
||||
Accumulate,
|
||||
|
@ -18,8 +18,8 @@ enum class Signedness {
|
|||
Unsigned,
|
||||
};
|
||||
|
||||
static void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
ShiftExtraBehavior behavior, Signedness signedness) {
|
||||
void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
ShiftExtraBehavior behavior, Signedness signedness) {
|
||||
const size_t esize = 64;
|
||||
const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend());
|
||||
|
||||
|
@ -39,8 +39,8 @@ static void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, V
|
|||
v.V_scalar(esize, Vd, result);
|
||||
}
|
||||
|
||||
static void RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
ShiftExtraBehavior behavior, Signedness signedness) {
|
||||
void RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
ShiftExtraBehavior behavior, Signedness signedness) {
|
||||
const size_t esize = 64;
|
||||
const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend());
|
||||
|
||||
|
@ -71,8 +71,8 @@ enum class ShiftDirection {
|
|||
Right,
|
||||
};
|
||||
|
||||
static void ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
ShiftDirection direction) {
|
||||
void ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
ShiftDirection direction) {
|
||||
const size_t esize = 64;
|
||||
|
||||
const u8 shift_amount = [&] {
|
||||
|
@ -106,6 +106,52 @@ static void ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec V
|
|||
v.V_scalar(esize, Vd, result);
|
||||
}
|
||||
|
||||
bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness sign) {
|
||||
const u32 immh_value = immh.ZeroExtend();
|
||||
|
||||
if ((immh_value & 0b1110) == 0b0000) {
|
||||
return v.ReservedValue();
|
||||
}
|
||||
|
||||
// TODO: We currently don't handle FP16, so bail like the ARM reference manual allows.
|
||||
if ((immh_value & 0b1110) == 0b0010) {
|
||||
return v.ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = (immh_value & 0b1000) != 0 ? 64 : 32;
|
||||
const size_t concat = concatenate(immh, immb).ZeroExtend();
|
||||
const size_t fbits = (esize * 2) - concat;
|
||||
|
||||
const IR::U32U64 operand = v.V_scalar(esize, Vn);
|
||||
const IR::U32U64 result = [&]() -> IR::U32U64 {
|
||||
if (esize == 64) {
|
||||
if (sign == Signedness::Signed) {
|
||||
return v.ir.FPDoubleToFixedS64(operand, fbits, FP::RoundingMode::TowardsZero);
|
||||
}
|
||||
|
||||
return v.ir.FPDoubleToFixedU64(operand, fbits, FP::RoundingMode::TowardsZero);
|
||||
}
|
||||
|
||||
if (sign == Signedness::Signed) {
|
||||
return v.ir.FPSingleToFixedS32(operand, fbits, FP::RoundingMode::TowardsZero);
|
||||
}
|
||||
|
||||
return v.ir.FPSingleToFixedU32(operand, fbits, FP::RoundingMode::TowardsZero);
|
||||
}();
|
||||
|
||||
v.V_scalar(esize, Vd, result);
|
||||
return true;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
bool TranslatorVisitor::FCVTZS_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
||||
return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Signed);
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::FCVTZU_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
||||
return ScalarFPConvertWithRound(*this, immh, immb, Vn, Vd, Signedness::Unsigned);
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SLI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
|
||||
if (!immh.Bit<3>()) {
|
||||
return ReservedValue();
|
||||
|
|
Loading…
Reference in a new issue