diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index 7b049dde..d5c26c6d 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -280,9 +280,9 @@ INST(thumb32_USADA8, "USADA8", "111110110111nnnnaaaadd // Long Multiply, Long Multiply Accumulate, and Divide INST(thumb32_SMULL, "SMULL", "111110111000nnnnllllhhhh0000mmmm") -//INST(thumb32_SDIV, "SDIV", "111110111001------------1111----") +INST(thumb32_SDIV, "SDIV", "111110111001nnnn1111dddd1111mmmm") INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhhhh0000mmmm") -//INST(thumb32_UDIV, "UDIV", "111110111011------------1111----") +INST(thumb32_UDIV, "UDIV", "111110111011nnnn1111dddd1111mmmm") INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhhhh0000mmmm") INST(thumb32_SMLALXY, "SMLALXY", "111110111100nnnnllllhhhh10NMmmmm") INST(thumb32_SMLALD, "SMLALD", "111110111100nnnnllllhhhh110Mmmmm") diff --git a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp index 82ef1f13..ecf66f01 100644 --- a/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp +++ b/src/frontend/A32/translate/impl/thumb32_long_multiply.cpp @@ -6,6 +6,26 @@ #include "frontend/A32/translate/impl/translate_thumb.h" namespace Dynarmic::A32 { +namespace { +using DivideFunction = IR::U32U64 (IREmitter::*)(const IR::U32U64&, const IR::U32U64&); + +bool DivideOperation(ThumbTranslatorVisitor& v, Reg d, Reg m, Reg n, DivideFunction fn) { + if (d == Reg::PC || m == Reg::PC || n == Reg::PC) { + return v.UnpredictableInstruction(); + } + + const IR::U32 operand1 = v.ir.GetRegister(n); + const IR::U32 operand2 = v.ir.GetRegister(m); + const IR::U32 result = (v.ir.*fn)(operand1, operand2); + + v.ir.SetRegister(d, result); + return true; +} +} // Anonymous namespace + +bool ThumbTranslatorVisitor::thumb32_SDIV(Reg n, Reg d, Reg m) { + return DivideOperation(*this, d, m, n, &IREmitter::SignedDiv); +} bool ThumbTranslatorVisitor::thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { @@ -133,6 +153,10 @@ bool ThumbTranslatorVisitor::thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m) { return true; } +bool ThumbTranslatorVisitor::thumb32_UDIV(Reg n, Reg d, Reg m) { + return DivideOperation(*this, d, m, n, &IREmitter::UnsignedDiv); +} + bool ThumbTranslatorVisitor::thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m) { if (dLo == Reg::PC || dHi == Reg::PC || n == Reg::PC || m == Reg::PC) { return UnpredictableInstruction(); diff --git a/src/frontend/A32/translate/impl/translate_thumb.h b/src/frontend/A32/translate/impl/translate_thumb.h index 008beaf6..67e08406 100644 --- a/src/frontend/A32/translate/impl/translate_thumb.h +++ b/src/frontend/A32/translate/impl/translate_thumb.h @@ -117,11 +117,13 @@ struct ThumbTranslatorVisitor final { bool thumb32_UDF(); // thumb32 long multiply, long multiply accumulate, and divide instructions + bool thumb32_SDIV(Reg n, Reg d, Reg m); bool thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_SMLALD(Reg n, Reg dLo, Reg dHi, bool M, Reg m); bool thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m); bool thumb32_SMLSLD(Reg n, Reg dLo, Reg dHi, bool M, Reg m); bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m); + bool thumb32_UDIV(Reg n, Reg d, Reg m); bool thumb32_UMAAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m); bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m);