A32: Implement ARM-mode MLS

This commit is contained in:
Lioncash 2019-04-21 21:37:27 -04:00 committed by MerryMage
parent 8b338b7def
commit 7fc3bd689d
5 changed files with 25 additions and 0 deletions

View file

@ -199,6 +199,7 @@ INST(arm_UDIV, "UDIV", "cccc01110011dddd1111mmmm0001nnnn
// Multiply (Normal) instructions // Multiply (Normal) instructions
INST(arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn") // v2 INST(arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn") // v2
INST(arm_MLS, "MLS", "cccc00000110ddddaaaammmm1001nnnn") // v6T2
INST(arm_MUL, "MUL", "cccc0000000Sdddd0000mmmm1001nnnn") // v2 INST(arm_MUL, "MUL", "cccc0000000Sdddd0000mmmm1001nnnn") // v2
// Multiply (Long) instructions // Multiply (Long) instructions

View file

@ -664,6 +664,9 @@ public:
std::string arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n) { std::string arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n) {
return fmt::format("mla{}{} {}, {}, {}, {}", S ? "s" : "", CondToString(cond), d, n, m, a); return fmt::format("mla{}{} {}, {}, {}, {}", S ? "s" : "", CondToString(cond), d, n, m, a);
} }
std::string arm_MLS(Cond cond, Reg d, Reg a, Reg m, Reg n) {
return fmt::format("mls{} {}, {}, {}, {}", CondToString(cond), d, n, m, a);
}
std::string arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) { std::string arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) {
return fmt::format("mul{}{} {}, {}, {}", S ? "s" : "", CondToString(cond), d, n, m); return fmt::format("mul{}{} {}, {}, {}", S ? "s" : "", CondToString(cond), d, n, m);
} }

View file

@ -28,6 +28,25 @@ bool ArmTranslatorVisitor::arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n
return true; return true;
} }
// MLS<c> <Rd>, <Rn>, <Rm>, <Ra>
bool ArmTranslatorVisitor::arm_MLS(Cond cond, Reg d, Reg a, Reg m, Reg n) {
if (d == Reg::PC || a == Reg::PC || m == Reg::PC || n == Reg::PC) {
return UnpredictableInstruction();
}
if (!ConditionPassed(cond)) {
return true;
}
const IR::U32 operand1 = ir.GetRegister(n);
const IR::U32 operand2 = ir.GetRegister(m);
const IR::U32 operand3 = ir.GetRegister(a);
const IR::U32 result = ir.Sub(operand3, ir.Mul(operand1, operand2));
ir.SetRegister(d, result);
return true;
}
// MUL{S}<c> <Rd>, <Rn>, <Rm> // MUL{S}<c> <Rd>, <Rn>, <Rm>
bool ArmTranslatorVisitor::arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) { bool ArmTranslatorVisitor::arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) {
if (d == Reg::PC || n == Reg::PC || m == Reg::PC) { if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {

View file

@ -242,6 +242,7 @@ struct ArmTranslatorVisitor final {
// Multiply (Normal) instructions // Multiply (Normal) instructions
bool arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n); bool arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n);
bool arm_MLS(Cond cond, Reg d, Reg a, Reg m, Reg n);
bool arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n); bool arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n);
// Multiply (Long) instructions // Multiply (Long) instructions

View file

@ -848,6 +848,7 @@ TEST_CASE("Fuzz ARM multiply instructions", "[JitX64][A32]") {
const std::array instructions = { const std::array instructions = {
InstructionGenerator("cccc0000001Sddddaaaammmm1001nnnn", validate_d_a_m_n), // MLA InstructionGenerator("cccc0000001Sddddaaaammmm1001nnnn", validate_d_a_m_n), // MLA
InstructionGenerator("cccc00000110ddddaaaammmm1001nnnn", validate_d_a_m_n), // MLS
InstructionGenerator("cccc0000000Sdddd0000mmmm1001nnnn", validate_d_m_n), // MUL InstructionGenerator("cccc0000000Sdddd0000mmmm1001nnnn", validate_d_m_n), // MUL
InstructionGenerator("cccc0000111Sddddaaaammmm1001nnnn", validate_h_l_m_n), // SMLAL InstructionGenerator("cccc0000111Sddddaaaammmm1001nnnn", validate_h_l_m_n), // SMLAL