VFP: Implement VMOV (all variants)

This commit is contained in:
MerryMage 2016-08-07 19:25:12 +01:00
parent aba705f6b9
commit a2c2db277b
11 changed files with 301 additions and 27 deletions

View file

@ -192,6 +192,123 @@ bool ArmTranslatorVisitor::vfp2_VDIV(Cond cond, bool D, size_t Vn, size_t Vd, bo
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_u32_f64(Cond cond, size_t Vd, Reg t, bool D) {
ExtReg d = ToExtReg(true, Vd, D);
if (t == Reg::PC)
return UnpredictableInstruction();
// VMOV.32 <Dd[0]>, <Rt>
if (ConditionPassed(cond)) {
auto d_f64 = ir.GetExtendedRegister(d);
auto t_u32 = ir.GetRegister(t);
auto d_u64 = ir.TransferFromFP64(d_f64);
auto result = ir.Pack2x32To1x64(t_u32, ir.MostSignificantWord(d_u64).result);
ir.SetExtendedRegister(d, ir.TransferToFP64(result));
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_f64_u32(Cond cond, size_t Vn, Reg t, bool N) {
ExtReg n = ToExtReg(true, Vn, N);
if (t == Reg::PC)
return UnpredictableInstruction();
// VMOV.32 <Rt>, <Dn[0]>
if (ConditionPassed(cond)) {
auto n_f64 = ir.GetExtendedRegister(n);
ir.SetRegister(t, ir.LeastSignificantWord(ir.TransferFromFP64(n_f64)));
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_u32_f32(Cond cond, size_t Vn, Reg t, bool N) {
ExtReg n = ToExtReg(false, Vn, N);
if (t == Reg::PC)
return UnpredictableInstruction();
// VMOV <Sn>, <Rt>
if (ConditionPassed(cond)) {
ir.SetExtendedRegister(n, ir.TransferToFP32(ir.GetRegister(t)));
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_f32_u32(Cond cond, size_t Vn, Reg t, bool N) {
ExtReg n = ToExtReg(false, Vn, N);
if (t == Reg::PC)
return UnpredictableInstruction();
// VMOV <Rt>, <Sn>
if (ConditionPassed(cond)) {
ir.SetRegister(t, ir.TransferFromFP32(ir.GetExtendedRegister(n)));
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_2u32_2f32(Cond cond, Reg t2, Reg t, bool M, size_t Vm) {
ExtReg m = ToExtReg(false, Vm, M);
if (t == Reg::PC || t2 == Reg::PC || m == ExtReg::S31)
return UnpredictableInstruction();
// VMOV <Sm>, <Sm1>, <Rt>, <Rt2>
if (ConditionPassed(cond)) {
ir.SetExtendedRegister(m, ir.TransferToFP32(ir.GetRegister(t)));
ir.SetExtendedRegister(m+1, ir.TransferToFP32(ir.GetRegister(t2)));
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_2f32_2u32(Cond cond, Reg t2, Reg t, bool M, size_t Vm) {
ExtReg m = ToExtReg(false, Vm, M);
if (t == Reg::PC || t2 == Reg::PC || m == ExtReg::S31)
return UnpredictableInstruction();
if (t == t2)
return UnpredictableInstruction();
// VMOV <Rt>, <Rt2>, <Sm>, <Sm1>
if (ConditionPassed(cond)) {
ir.SetRegister(t, ir.TransferFromFP32(ir.GetExtendedRegister(m)));
ir.SetRegister(t2, ir.TransferFromFP32(ir.GetExtendedRegister(m+1)));
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_2u32_f64(Cond cond, Reg t2, Reg t, bool M, size_t Vm) {
ExtReg m = ToExtReg(true, Vm, M);
if (t == Reg::PC || t2 == Reg::PC || m == ExtReg::S31)
return UnpredictableInstruction();
// VMOV<c> <Dm>, <Rt>, <Rt2>
if (ConditionPassed(cond)) {
auto value = ir.Pack2x32To1x64(ir.GetRegister(t), ir.GetRegister(t2));
ir.SetExtendedRegister(m, ir.TransferToFP64(value));
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M, size_t Vm) {
ExtReg m = ToExtReg(true, Vm, M);
if (t == Reg::PC || t2 == Reg::PC || m == ExtReg::S31)
return UnpredictableInstruction();
if (t == t2)
return UnpredictableInstruction();
// VMOV<c> <Rt>, <Rt2>, <Dm>
if (ConditionPassed(cond)) {
auto value = ir.TransferFromFP64(ir.GetExtendedRegister(m));
ir.SetRegister(t, ir.LeastSignificantWord(value));
ir.SetRegister(t2, ir.MostSignificantWord(value).result);
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VMOV_reg(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm) {
if (ir.current_location.FPSCR_Len() != 1 || ir.current_location.FPSCR_Stride() != 1)
return InterpretThisInstruction(); // TODO: Vectorised floating point instructions
ExtReg d = ToExtReg(sz, Vd, D);
ExtReg m = ToExtReg(sz, Vm, M);
// VMOV.{F32,F64} <{S,D}d>, <{S,D}m>
if (ConditionPassed(cond)) {
ir.SetExtendedRegister(d, ir.GetExtendedRegister(m));
}
return true;
}
bool ArmTranslatorVisitor::vfp2_VABS(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm) {
if (ir.current_location.FPSCR_Len() != 1 || ir.current_location.FPSCR_Stride() != 1)
return InterpretThisInstruction(); // TODO: Vectorised floating point instructions