A32: Implement ASIMD VMOV (general-purpose register to scalar)

This commit is contained in:
MerryMage 2020-06-20 23:40:48 +01:00
parent 7ec22b4e1d
commit fda4e11887
4 changed files with 88 additions and 1 deletions

View file

@ -44,6 +44,9 @@ INST(vfp_VMOV_2u32_2f32, "VMOV (2xcore to 2xf32)", "cccc11000100uuuutttt10100
INST(vfp_VMOV_2f32_2u32, "VMOV (2xf32 to 2xcore)", "cccc11000101uuuutttt101000M1mmmm") // VFPv2
INST(vfp_VMOV_2u32_f64, "VMOV (2xcore to f64)", "cccc11000100uuuutttt101100M1mmmm") // VFPv2
INST(vfp_VMOV_f64_2u32, "VMOV (f64 to 2xcore)", "cccc11000101uuuutttt101100M1mmmm") // VFPv2
INST(vfp_VMOV_from_i32, "VMOV (core to i32)" , "cccc111000i0nnnntttt1011N0010000") // VFPv4
INST(vfp_VMOV_from_i16, "VMOV (core to i16)" , "cccc111000i0nnnntttt1011Ni110000") // ASIMD
INST(vfp_VMOV_from_i8, "VMOV (core to i8)", "cccc111001i0nnnntttt1011Nii10000") // ASIMD
INST(vfp_VMOV_to_i32, "VMOV (i32 to core)" , "cccc111000i1nnnntttt1011N0010000") // VFPv4
INST(vfp_VMOV_to_i16, "VMOV (i16 to core)" , "cccc1110U0i1nnnntttt1011Ni110000") // ASIMD
INST(vfp_VMOV_to_i8, "VMOV (i8 to core)", "cccc1110U1i1nnnntttt1011Nii10000") // ASIMD

View file

@ -1347,6 +1347,21 @@ public:
return fmt::format("vmov{} {}, {}, {}", CondToString(cond), t, t2, FPRegStr(true, Vm, M));
}
std::string vfp_VMOV_from_i32(Cond cond, Imm<1> i, size_t Vd, Reg t, bool D) {
const size_t index = i.ZeroExtend();
return fmt::format("vmov{}.32 {}[{}], {}", CondToString(cond), FPRegStr(true, Vd, D), index, t);
}
std::string vfp_VMOV_from_i16(Cond cond, Imm<1> i1, size_t Vd, Reg t, bool D, Imm<1> i2) {
const size_t index = concatenate(i1, i2).ZeroExtend();
return fmt::format("vmov{}.{}16 {}[{}], {}", CondToString(cond), FPRegStr(true, Vd, D), index, t);
}
std::string vfp_VMOV_from_i8(Cond cond, Imm<1> i1, size_t Vd, Reg t, bool D, Imm<2> i2) {
const size_t index = concatenate(i1, i2).ZeroExtend();
return fmt::format("vmov{}.{}8 {}[{}], {}", CondToString(cond), FPRegStr(true, Vd, D), index, t);
}
std::string vfp_VMOV_to_i32(Cond cond, Imm<1> i, size_t Vn, Reg t, bool N) {
const size_t index = i.ZeroExtend();
return fmt::format("vmov{}.32 {}, {}[{}]", CondToString(cond), t, FPRegStr(true, Vn, N), index);

View file

@ -405,6 +405,9 @@ struct ArmTranslatorVisitor final {
bool vfp_VMOV_2f32_2u32(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
bool vfp_VMOV_2u32_f64(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
bool vfp_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
bool vfp_VMOV_from_i32(Cond cond, Imm<1> i, size_t Vd, Reg t, bool D);
bool vfp_VMOV_from_i16(Cond cond, Imm<1> i1, size_t Vd, Reg t, bool D, Imm<1> i2);
bool vfp_VMOV_from_i8(Cond cond, Imm<1> i1, size_t Vd, Reg t, bool D, Imm<2> i2);
bool vfp_VMOV_to_i32(Cond cond, Imm<1> i, size_t Vn, Reg t, bool N);
bool vfp_VMOV_to_i16(Cond cond, bool U, Imm<1> i1, size_t Vn, Reg t, bool N, Imm<1> i2);
bool vfp_VMOV_to_i8(Cond cond, bool U, Imm<1> i1, size_t Vn, Reg t, bool N, Imm<2> i2);

View file

@ -523,7 +523,73 @@ bool ArmTranslatorVisitor::vfp_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M, s
return true;
}
// VMOV<c>.{U16,S16} <Rt>, <Dn[x]>
// VMOV<c>.32 <Dn[x]>, <Rt>
bool ArmTranslatorVisitor::vfp_VMOV_from_i32(Cond cond, Imm<1> i, size_t Vd, Reg t, bool D) {
if (!ConditionPassed(cond)) {
return true;
}
if (t == Reg::R15) {
// TODO: v8 removes UPREDICTABLE for R13
return UnpredictableInstruction();
}
const size_t index = i.ZeroExtend();
const auto d = ToVector(false, Vd, D);
const auto reg_d = ir.GetVector(d);
const auto scalar = ir.GetRegister(t);
const auto result = ir.VectorSetElement(32, reg_d, index, scalar);
ir.SetVector(d, result);
return true;
}
// VMOV<c>.16 <Dn[x]>, <Rt>
bool ArmTranslatorVisitor::vfp_VMOV_from_i16(Cond cond, Imm<1> i1, size_t Vd, Reg t, bool D, Imm<1> i2) {
if (!ConditionPassed(cond)) {
return true;
}
if (t == Reg::R15) {
// TODO: v8 removes UPREDICTABLE for R13
return UnpredictableInstruction();
}
const size_t index = concatenate(i1, i2).ZeroExtend();
const auto d = ToVector(false, Vd, D);
const auto reg_d = ir.GetVector(d);
const auto scalar = ir.LeastSignificantHalf(ir.GetRegister(t));
const auto result = ir.VectorSetElement(16, reg_d, index, scalar);
ir.SetVector(d, result);
return true;
}
// VMOV<c>.8 <Dn[x]>, <Rt>
bool ArmTranslatorVisitor::vfp_VMOV_from_i8(Cond cond, Imm<1> i1, size_t Vd, Reg t, bool D, Imm<2> i2) {
if (!ConditionPassed(cond)) {
return true;
}
if (t == Reg::R15) {
// TODO: v8 removes UPREDICTABLE for R13
return UnpredictableInstruction();
}
const size_t index = concatenate(i1, i2).ZeroExtend();
const auto d = ToVector(false, Vd, D);
const auto reg_d = ir.GetVector(d);
const auto scalar = ir.LeastSignificantByte(ir.GetRegister(t));
const auto result = ir.VectorSetElement(8, reg_d, index, scalar);
ir.SetVector(d, result);
return true;
}
// VMOV<c>.32 <Rt>, <Dn[x]>
bool ArmTranslatorVisitor::vfp_VMOV_to_i32(Cond cond, Imm<1> i, size_t Vn, Reg t, bool N) {
if (!ConditionPassed(cond)) {
return true;