Implement some multiplies

This commit is contained in:
Tillmann Karras 2016-08-05 02:03:23 +01:00
parent 72c503016c
commit eb2e6e8bea
4 changed files with 174 additions and 21 deletions

View file

@ -246,15 +246,15 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
//INST(&V::arm_USAT16, "USAT16", "cccc01101110vvvvdddd11110011nnnn"), // v6
// Multiply (Normal) instructions
//INST(&V::arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn"), // v2
//INST(&V::arm_MUL, "MUL", "cccc0000000Sdddd0000mmmm1001nnnn"), // v2
INST(&V::arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn"), // v2
INST(&V::arm_MUL, "MUL", "cccc0000000Sdddd0000mmmm1001nnnn"), // v2
// Multiply (Long) instructions
//INST(&V::arm_SMLAL, "SMLAL", "cccc0000111Sddddaaaammmm1001nnnn"), // v3M
//INST(&V::arm_SMULL, "SMULL", "cccc0000110Sddddaaaammmm1001nnnn"), // v3M
//INST(&V::arm_UMAAL, "UMAAL", "cccc00000100ddddaaaammmm1001nnnn"), // v6
//INST(&V::arm_UMLAL, "UMLAL", "cccc0000101Sddddaaaammmm1001nnnn"), // v3M
//INST(&V::arm_UMULL, "UMULL", "cccc0000100Sddddaaaammmm1001nnnn"), // v3M
INST(&V::arm_SMLAL, "SMLAL", "cccc0000111Sddddaaaammmm1001nnnn"), // v3M
INST(&V::arm_SMULL, "SMULL", "cccc0000110Sddddaaaammmm1001nnnn"), // v3M
INST(&V::arm_UMAAL, "UMAAL", "cccc00000100ddddaaaammmm1001nnnn"), // v6
INST(&V::arm_UMLAL, "UMLAL", "cccc0000101Sddddaaaammmm1001nnnn"), // v3M
INST(&V::arm_UMULL, "UMULL", "cccc0000100Sddddaaaammmm1001nnnn"), // v3M
// Multiply (Halfword) instructions
//INST(&V::arm_SMLALxy, "SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn"), // v5xP

View file

@ -383,15 +383,29 @@ public:
std::string arm_USAT16(Cond cond, Imm4 sat_imm, Reg d, Reg n) { return "ice"; }
// Multiply (Normal) instructions
std::string arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n) { return "ice"; }
std::string arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) { return "ice"; }
std::string arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n) {
return Common::StringFromFormat("mla%s%s %s, %s, %s, %s", S ? "s" : "", CondToString(cond), RegToString(d), RegToString(n), RegToString(m), RegToString(a));
}
std::string arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) {
return Common::StringFromFormat("mul%s%s %s, %s, %s", S ? "s" : "", CondToString(cond), RegToString(d), RegToString(n), RegToString(m));
}
// Multiply (Long) instructions
std::string arm_SMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) { return "ice"; }
std::string arm_SMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) { return "ice"; }
std::string arm_UMAAL(Cond cond, Reg dHi, Reg dLo, Reg m, Reg n) { return "ice"; }
std::string arm_UMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) { return "ice"; }
std::string arm_UMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) { return "ice"; }
std::string arm_SMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
return Common::StringFromFormat("smlal%s%s %s, %s, %s, %s", S ? "s" : "", CondToString(cond), RegToString(dLo), RegToString(dHi), RegToString(n), RegToString(m));
}
std::string arm_SMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
return Common::StringFromFormat("smull%s%s %s, %s, %s, %s", S ? "s" : "", CondToString(cond), RegToString(dLo), RegToString(dHi), RegToString(n), RegToString(m));
}
std::string arm_UMAAL(Cond cond, Reg dHi, Reg dLo, Reg m, Reg n) {
return Common::StringFromFormat("umaal%s %s, %s, %s, %s", CondToString(cond), RegToString(dLo), RegToString(dHi), RegToString(n), RegToString(m));
}
std::string arm_UMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
return Common::StringFromFormat("umlal%s%s %s, %s, %s, %s", S ? "s" : "", CondToString(cond), RegToString(dLo), RegToString(dHi), RegToString(n), RegToString(m));
}
std::string arm_UMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
return Common::StringFromFormat("umull%s%s %s, %s, %s, %s", S ? "s" : "", CondToString(cond), RegToString(dLo), RegToString(dHi), RegToString(n), RegToString(m));
}
// Multiply (Halfword) instructions
std::string arm_SMLALxy(Cond cond, Reg dHi, Reg dLo, Reg m, bool M, bool N, Reg n) { return "ice"; }

View file

@ -11,33 +11,137 @@ namespace Arm {
// Multiply (Normal) instructions
bool ArmTranslatorVisitor::arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n) {
return InterpretThisInstruction();
if (d == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
if (ConditionPassed(cond)) {
auto result = ir.Add(ir.Mul(ir.GetRegister(n), ir.GetRegister(m)), ir.GetRegister(a));
ir.SetRegister(d, result);
if (S) {
ir.SetNFlag(ir.MostSignificantBit(result));
ir.SetZFlag(ir.IsZero(result));
}
}
return true;
}
bool ArmTranslatorVisitor::arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n) {
return InterpretThisInstruction();
if (d == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
if (ConditionPassed(cond)) {
auto result = ir.Mul(ir.GetRegister(n), ir.GetRegister(m));
ir.SetRegister(d, result);
if (S) {
ir.SetNFlag(ir.MostSignificantBit(result));
ir.SetZFlag(ir.IsZero(result));
}
}
return true;
}
// Multiply (Long) instructions
bool ArmTranslatorVisitor::arm_SMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
return InterpretThisInstruction();
if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
if (dLo == dHi)
return UnpredictableInstruction();
if (ConditionPassed(cond)) {
auto n64 = ir.SignExtendWordToLong(ir.GetRegister(n));
auto m64 = ir.SignExtendWordToLong(ir.GetRegister(m));
auto product = ir.Mul64(n64, m64);
auto addend = ir.Pack2x32To1x64(ir.GetRegister(dLo), ir.GetRegister(dHi));
auto result = ir.Add64(product, addend);
auto lo = ir.LeastSignificantWord(result);
auto hi = ir.MostSignificantWord(result);
ir.SetRegister(dLo, lo);
ir.SetRegister(dHi, hi);
if (S) {
ir.SetNFlag(ir.MostSignificantBit(hi));
ir.SetZFlag(ir.IsZero64(result));
}
}
return true;
}
bool ArmTranslatorVisitor::arm_SMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
return InterpretThisInstruction();
if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
if (dLo == dHi)
return UnpredictableInstruction();
if (ConditionPassed(cond)) {
auto n64 = ir.SignExtendWordToLong(ir.GetRegister(n));
auto m64 = ir.SignExtendWordToLong(ir.GetRegister(m));
auto result = ir.Mul64(n64, m64);
auto lo = ir.LeastSignificantWord(result);
auto hi = ir.MostSignificantWord(result);
ir.SetRegister(dLo, lo);
ir.SetRegister(dHi, hi);
if (S) {
ir.SetNFlag(ir.MostSignificantBit(hi));
ir.SetZFlag(ir.IsZero64(result));
}
}
return true;
}
bool ArmTranslatorVisitor::arm_UMAAL(Cond cond, Reg dHi, Reg dLo, Reg m, Reg n) {
return InterpretThisInstruction();
if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
if (dLo == dHi)
return UnpredictableInstruction();
if (ConditionPassed(cond)) {
auto lo64 = ir.ZeroExtendWordToLong(ir.GetRegister(dLo));
auto hi64 = ir.ZeroExtendWordToLong(ir.GetRegister(dHi));
auto n64 = ir.ZeroExtendWordToLong(ir.GetRegister(n));
auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m));
auto result = ir.Add64(ir.Add64(ir.Mul64(n64, m64), hi64), lo64);
ir.SetRegister(dLo, ir.LeastSignificantWord(result));
ir.SetRegister(dHi, ir.MostSignificantWord(result));
}
return true;
}
bool ArmTranslatorVisitor::arm_UMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
return InterpretThisInstruction();
if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
if (dLo == dHi)
return UnpredictableInstruction();
if (ConditionPassed(cond)) {
auto addend = ir.Pack2x32To1x64(ir.GetRegister(dLo), ir.GetRegister(dHi));
auto n64 = ir.ZeroExtendWordToLong(ir.GetRegister(n));
auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m));
auto result = ir.Add64(ir.Mul64(n64, m64), addend);
auto lo = ir.LeastSignificantWord(result);
auto hi = ir.MostSignificantWord(result);
ir.SetRegister(dLo, lo);
ir.SetRegister(dHi, hi);
if (S) {
ir.SetNFlag(ir.MostSignificantBit(hi));
ir.SetZFlag(ir.IsZero64(result));
}
}
return true;
}
bool ArmTranslatorVisitor::arm_UMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n) {
return InterpretThisInstruction();
if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
if (dLo == dHi)
return UnpredictableInstruction();
if (ConditionPassed(cond)) {
auto n64 = ir.ZeroExtendWordToLong(ir.GetRegister(n));
auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m));
auto result = ir.Mul64(n64, m64);
auto lo = ir.LeastSignificantWord(result);
auto hi = ir.MostSignificantWord(result);
ir.SetRegister(dLo, lo);
ir.SetRegister(dHi, hi);
if (S) {
ir.SetNFlag(ir.MostSignificantBit(hi));
ir.SetZFlag(ir.IsZero64(result));
}
}
return true;
}