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----
|
// cccc1110________----101-__-0----
|
||||||
|
|
||||||
// Floating-point three-register data processing instructions
|
// Floating-point three-register data processing instructions
|
||||||
// VMLA
|
INST(&V::vfp2_VMLA, "VMLA", "cccc11100D00nnnndddd101zN0M0mmmm"),
|
||||||
// VMLS
|
INST(&V::vfp2_VMLS, "VMLS", "cccc11100D00nnnndddd101zN1M0mmmm"),
|
||||||
// VNMLA
|
INST(&V::vfp2_VNMLS, "VNMLS", "cccc11100D01nnnndddd101zN0M0mmmm"),
|
||||||
// VNMLS
|
INST(&V::vfp2_VNMLA, "VNMLA", "cccc11100D01nnnndddd101zN1M0mmmm"),
|
||||||
INST(&V::vfp2_VMUL, "VMUL", "cccc11100D10nnnndddd101zN0M0mmmm"),
|
INST(&V::vfp2_VMUL, "VMUL", "cccc11100D10nnnndddd101zN0M0mmmm"),
|
||||||
INST(&V::vfp2_VNMUL, "VNMUL", "cccc11100D10nnnndddd101zN1M0mmmm"),
|
INST(&V::vfp2_VNMUL, "VNMUL", "cccc11100D10nnnndddd101zN1M0mmmm"),
|
||||||
INST(&V::vfp2_VADD, "VADD", "cccc11100D11nnnndddd101zN0M0mmmm"),
|
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); };
|
const auto matches_instruction = [instruction](const auto& matcher){ return matcher.Matches(instruction); };
|
||||||
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||||
|
|
|
@ -560,10 +560,6 @@ public:
|
||||||
std::string arm_SRS() { return "ice"; }
|
std::string arm_SRS() { return "ice"; }
|
||||||
|
|
||||||
// Floating point arithmetic instructions
|
// 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) {
|
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());
|
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());
|
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) {
|
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());
|
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) {
|
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());
|
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
|
// 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_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_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_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);
|
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
|
// 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;
|
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) {
|
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)
|
if (ir.current_location.FPSCR_Len() != 1 || ir.current_location.FPSCR_Stride() != 1)
|
||||||
return InterpretThisInstruction(); // TODO: Vectorised floating point instructions
|
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;
|
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) {
|
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)
|
if (ir.current_location.FPSCR_Len() != 1 || ir.current_location.FPSCR_Stride() != 1)
|
||||||
return InterpretThisInstruction(); // TODO: Vectorised floating point instructions
|
return InterpretThisInstruction(); // TODO: Vectorised floating point instructions
|
||||||
|
|
Loading…
Reference in a new issue