mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-01-07 15:08:22 +01:00
A32: Implement VFPv3 VCT (between floating-point and fixed-point)
This commit is contained in:
parent
48b2ffdde9
commit
3ea49fc6d6
9 changed files with 322 additions and 54 deletions
|
|
@ -427,8 +427,10 @@ struct ArmTranslatorVisitor final {
|
|||
bool vfp_VRINTZ(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||
bool vfp_VCVT_f_to_f(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||
bool vfp_VCVT_from_int(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm);
|
||||
bool vfp_VCVT_from_fixed(Cond cond, bool D, bool U, size_t Vd, bool sz, bool sx, Imm<1> i, Imm<4> imm4);
|
||||
bool vfp_VCVT_to_u32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm);
|
||||
bool vfp_VCVT_to_s32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm);
|
||||
bool vfp_VCVT_to_fixed(Cond cond, bool D, bool U, size_t Vd, bool sz, bool sx, Imm<1> i, Imm<4> imm4);
|
||||
bool vfp_VRINT_rm(bool D, size_t rm, size_t Vd, bool sz, bool M, size_t Vm);
|
||||
bool vfp_VCVT_rm(bool D, size_t rm, size_t Vd, bool sz, bool U, bool M, size_t Vm);
|
||||
|
||||
|
|
|
|||
|
|
@ -966,6 +966,38 @@ bool ArmTranslatorVisitor::vfp_VCVT_from_int(Cond cond, bool D, size_t Vd, bool
|
|||
return true;
|
||||
}
|
||||
|
||||
// VCVT.F32.{S16,U16,S32,U32} <Sdm>, <Sdm>
|
||||
// VCVT.F64.{S16,U16,S32,U32} <Ddm>, <Ddm>
|
||||
bool ArmTranslatorVisitor::vfp_VCVT_from_fixed(Cond cond, bool D, bool U, size_t Vd, bool sz, bool sx, Imm<1> i, Imm<4> imm4) {
|
||||
if (!ConditionPassed(cond)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const size_t size = sx ? 32 : 16;
|
||||
const size_t fbits = size - concatenate(imm4, i).ZeroExtend();
|
||||
|
||||
if (fbits > size) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
const auto d = ToExtReg(sz, Vd, D);
|
||||
const auto rounding_mode = FP::RoundingMode::ToNearest_TieEven;
|
||||
const auto reg_d = ir.GetExtendedRegister(d);
|
||||
const auto source = ir.LeastSignificant(size, reg_d);
|
||||
|
||||
if (sz) {
|
||||
const auto result = U ? ir.FPUnsignedFixedToDouble(source, fbits, rounding_mode)
|
||||
: ir.FPSignedFixedToDouble(source, fbits, rounding_mode);
|
||||
ir.SetExtendedRegister(d, result);
|
||||
} else {
|
||||
const auto result = U ? ir.FPUnsignedFixedToSingle(source, fbits, rounding_mode)
|
||||
: ir.FPSignedFixedToSingle(source, fbits, rounding_mode);
|
||||
ir.SetExtendedRegister(d, result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// VCVT{,R}.U32.F32 <Sd>, <Sm>
|
||||
// VCVT{,R}.U32.F64 <Sd>, <Dm>
|
||||
bool ArmTranslatorVisitor::vfp_VCVT_to_u32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm) {
|
||||
|
|
@ -998,6 +1030,42 @@ bool ArmTranslatorVisitor::vfp_VCVT_to_s32(Cond cond, bool D, size_t Vd, bool sz
|
|||
return true;
|
||||
}
|
||||
|
||||
// VCVT.{S16,U16,S32,U32}.F32 <Sdm>, <Sdm>
|
||||
// VCVT.{S16,U16,S32,U32}.F64 <Ddm>, <Ddm>
|
||||
bool ArmTranslatorVisitor::vfp_VCVT_to_fixed(Cond cond, bool D, bool U, size_t Vd, bool sz, bool sx, Imm<1> i, Imm<4> imm4) {
|
||||
if (!ConditionPassed(cond)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const size_t size = sx ? 32 : 16;
|
||||
const size_t fbits = size - concatenate(imm4, i).ZeroExtend();
|
||||
|
||||
if (fbits > size) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
const auto d = ToExtReg(sz, Vd, D);
|
||||
const auto rounding_mode = FP::RoundingMode::TowardsZero;
|
||||
const auto reg_d = ir.GetExtendedRegister(d);
|
||||
|
||||
const auto result = [&]() -> IR::U16U32U64 {
|
||||
if (sx) {
|
||||
return U ? ir.FPToFixedU32(reg_d, fbits, rounding_mode)
|
||||
: ir.FPToFixedS32(reg_d, fbits, rounding_mode);
|
||||
} else {
|
||||
return U ? ir.FPToFixedU16(reg_d, fbits, rounding_mode)
|
||||
: ir.FPToFixedS16(reg_d, fbits, rounding_mode);
|
||||
}
|
||||
}();
|
||||
|
||||
if (sz) {
|
||||
ir.SetExtendedRegister(d, U ? ir.ZeroExtendToLong(result) : ir.SignExtendToLong(result));
|
||||
} else {
|
||||
ir.SetExtendedRegister(d, U ? ir.ZeroExtendToWord(result) : ir.SignExtendToWord(result));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// VRINT{A,N,P,M}.F32 <Sd>, <Sm>
|
||||
// VRINT{A,N,P,M}.F64 <Dd>, <Dm>
|
||||
bool ArmTranslatorVisitor::vfp_VRINT_rm(bool D, size_t rm, size_t Vd, bool sz, bool M, size_t Vm) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue