VFP: Implement VMLA, VMLS, VNMLA, VNMLS
This commit is contained in:
parent
3f1345a1a5
commit
da33af5abe
4 changed files with 112 additions and 9 deletions
|
@ -64,10 +64,10 @@ boost::optional<const VFP2Matcher<V>&> DecodeVFP2(u32 instruction) {
|
|||
// cccc1110________----101-__-0----
|
||||
|
||||
// Floating-point three-register data processing instructions
|
||||
// VMLA
|
||||
// VMLS
|
||||
// VNMLA
|
||||
// VNMLS
|
||||
INST(&V::vfp2_VMLA, "VMLA", "cccc11100D00nnnndddd101zN0M0mmmm"),
|
||||
INST(&V::vfp2_VMLS, "VMLS", "cccc11100D00nnnndddd101zN1M0mmmm"),
|
||||
INST(&V::vfp2_VNMLS, "VNMLS", "cccc11100D01nnnndddd101zN0M0mmmm"),
|
||||
INST(&V::vfp2_VNMLA, "VNMLA", "cccc11100D01nnnndddd101zN1M0mmmm"),
|
||||
INST(&V::vfp2_VMUL, "VMUL", "cccc11100D10nnnndddd101zN0M0mmmm"),
|
||||
INST(&V::vfp2_VNMUL, "VNMUL", "cccc11100D10nnnndddd101zN1M0mmmm"),
|
||||
INST(&V::vfp2_VADD, "VADD", "cccc11100D11nnnndddd101zN0M0mmmm"),
|
||||
|
@ -99,6 +99,9 @@ boost::optional<const VFP2Matcher<V>&> DecodeVFP2(u32 instruction) {
|
|||
|
||||
};
|
||||
|
||||
if ((instruction & 0xF0000000) == 0xF0000000)
|
||||
return boost::none; // Don't try matching any unconditional instructions.
|
||||
|
||||
const auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); };
|
||||
|
||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||
|
|
|
@ -560,10 +560,6 @@ public:
|
|||
std::string arm_SRS() { return "ice"; }
|
||||
|
||||
// Floating point arithmetic instructions
|
||||
std::string vfp2_VMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vmul%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
||||
std::string vfp2_VADD(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vadd%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
@ -572,10 +568,30 @@ public:
|
|||
return Common::StringFromFormat("vsub%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
||||
std::string vfp2_VMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vmul%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
||||
std::string vfp2_VMLA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vmla%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
||||
std::string vfp2_VMLS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vmls%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
||||
std::string vfp2_VNMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vnmul%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
||||
std::string vfp2_VNMLA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vnmla%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
||||
std::string vfp2_VNMLS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vnmls%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
||||
std::string vfp2_VDIV(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm) {
|
||||
return Common::StringFromFormat("vdiv%s.%s %s, %s, %s", CondToString(cond), sz ? "f64" : "f32", FPRegStr(sz, Vd, D).c_str(), FPRegStr(sz, Vn, N).c_str(), FPRegStr(sz, Vm, M).c_str());
|
||||
}
|
||||
|
|
|
@ -321,8 +321,12 @@ struct ArmTranslatorVisitor final {
|
|||
// Floating-point three-register data processing instructions
|
||||
bool vfp2_VADD(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VSUB(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VNMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VMLA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VMLS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VNMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VNMLA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VNMLS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
bool vfp2_VDIV(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||
|
||||
// Floating-point misc instructions
|
||||
|
|
|
@ -74,6 +74,46 @@ bool ArmTranslatorVisitor::vfp2_VMUL(Cond cond, bool D, size_t Vn, size_t Vd, bo
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::vfp2_VMLA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, 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 n = ToExtReg(sz, Vn, N);
|
||||
ExtReg m = ToExtReg(sz, Vm, M);
|
||||
// VMLA.{F32,F64} <{S,D}d>, <{S,D}n>, <{S,D}m>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto a = ir.GetExtendedRegister(n);
|
||||
auto b = ir.GetExtendedRegister(m);
|
||||
auto c = ir.GetExtendedRegister(d);
|
||||
auto result = sz
|
||||
? ir.FPAdd64(c, ir.FPMul64(a, b, true), true)
|
||||
: ir.FPAdd32(c, ir.FPMul32(a, b, true), true);
|
||||
ir.SetExtendedRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::vfp2_VMLS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, 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 n = ToExtReg(sz, Vn, N);
|
||||
ExtReg m = ToExtReg(sz, Vm, M);
|
||||
// VMLS.{F32,F64} <{S,D}d>, <{S,D}n>, <{S,D}m>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto a = ir.GetExtendedRegister(n);
|
||||
auto b = ir.GetExtendedRegister(m);
|
||||
auto c = ir.GetExtendedRegister(d);
|
||||
auto result = sz
|
||||
? ir.FPAdd64(c, ir.FPNeg64(ir.FPMul64(a, b, true)), true)
|
||||
: ir.FPAdd32(c, ir.FPNeg32(ir.FPMul32(a, b, true)), true);
|
||||
ir.SetExtendedRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::vfp2_VNMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, 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
|
||||
|
@ -93,6 +133,46 @@ bool ArmTranslatorVisitor::vfp2_VNMUL(Cond cond, bool D, size_t Vn, size_t Vd, b
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::vfp2_VNMLA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, 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 n = ToExtReg(sz, Vn, N);
|
||||
ExtReg m = ToExtReg(sz, Vm, M);
|
||||
// VNMLA.{F32,F64} <{S,D}d>, <{S,D}n>, <{S,D}m>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto a = ir.GetExtendedRegister(n);
|
||||
auto b = ir.GetExtendedRegister(m);
|
||||
auto c = ir.GetExtendedRegister(d);
|
||||
auto result = sz
|
||||
? ir.FPAdd64(ir.FPNeg64(c), ir.FPNeg64(ir.FPMul64(a, b, true)), true)
|
||||
: ir.FPAdd32(ir.FPNeg32(c), ir.FPNeg32(ir.FPMul32(a, b, true)), true);
|
||||
ir.SetExtendedRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::vfp2_VNMLS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, 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 n = ToExtReg(sz, Vn, N);
|
||||
ExtReg m = ToExtReg(sz, Vm, M);
|
||||
// VNMLS.{F32,F64} <{S,D}d>, <{S,D}n>, <{S,D}m>
|
||||
if (ConditionPassed(cond)) {
|
||||
auto a = ir.GetExtendedRegister(n);
|
||||
auto b = ir.GetExtendedRegister(m);
|
||||
auto c = ir.GetExtendedRegister(d);
|
||||
auto result = sz
|
||||
? ir.FPAdd64(ir.FPNeg64(c), ir.FPMul64(a, b, true), true)
|
||||
: ir.FPAdd32(ir.FPNeg32(c), ir.FPMul32(a, b, true), true);
|
||||
ir.SetExtendedRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::vfp2_VDIV(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, 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
|
||||
|
|
Loading…
Reference in a new issue