diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1c7387bf..22ba6b25 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ add_library(dynarmic frontend/A64/translate/impl/data_processing_bitfield.cpp frontend/A64/translate/impl/data_processing_conditional_select.cpp frontend/A64/translate/impl/data_processing_logical.cpp + frontend/A64/translate/impl/data_processing_multiply.cpp frontend/A64/translate/impl/data_processing_pcrel.cpp frontend/A64/translate/impl/data_processing_register.cpp frontend/A64/translate/impl/data_processing_shift.cpp diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index c21dbfe2..9458fe95 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -337,8 +337,8 @@ INST(CSINV, "CSINV", "z1011 INST(CSNEG, "CSNEG", "z1011010100mmmmmcccc01nnnnnddddd") // Data Processing - Register - 3 source -//INST(MADD, "MADD", "z0011011000mmmmm0aaaaannnnnddddd") -//INST(MSUB, "MSUB", "z0011011000mmmmm1aaaaannnnnddddd") +INST(MADD, "MADD", "z0011011000mmmmm0aaaaannnnnddddd") +INST(MSUB, "MSUB", "z0011011000mmmmm1aaaaannnnnddddd") //INST(SMADDL, "SMADDL", "10011011001mmmmm0aaaaannnnnddddd") //INST(SMSUBL, "SMSUBL", "10011011001mmmmm1aaaaannnnnddddd") //INST(SMULH, "SMULH", "10011011010mmmmm011111nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/data_processing_multiply.cpp b/src/frontend/A64/translate/impl/data_processing_multiply.cpp new file mode 100644 index 00000000..fd5b080d --- /dev/null +++ b/src/frontend/A64/translate/impl/data_processing_multiply.cpp @@ -0,0 +1,39 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "frontend/A64/translate/impl/impl.h" + +namespace Dynarmic { +namespace A64 { + +bool TranslatorVisitor::MADD(bool sf, Reg Rm, Reg Ra, Reg Rn, Reg Rd) { + const size_t datasize = sf ? 64 : 32; + + const IR::U32U64 a = X(datasize, Ra); + const IR::U32U64 m = X(datasize, Rm); + const IR::U32U64 n = X(datasize, Rn); + + const IR::U32U64 result = ir.Add(a, ir.Mul(n, m)); + + X(datasize, Rd, result); + return true; +} + +bool TranslatorVisitor::MSUB(bool sf, Reg Rm, Reg Ra, Reg Rn, Reg Rd) { + const size_t datasize = sf ? 64 : 32; + + const IR::U32U64 a = X(datasize, Ra); + const IR::U32U64 m = X(datasize, Rm); + const IR::U32U64 n = X(datasize, Rn); + + const IR::U32U64 result = ir.Sub(a, ir.Mul(n, m)); + + X(datasize, Rd, result); + return true; +} + +} // namespace A64 +} // namespace Dynarmic diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 6355e2be..16b2b77f 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -265,6 +265,14 @@ U64 IREmitter::Mul(const U64& a, const U64& b) { return Inst(Opcode::Mul64, a, b); } +U32U64 IREmitter::Mul(const U32U64& a, const U32U64& b) { + if (a.GetType() == Type::U32) { + return Inst(Opcode::Mul32, a, b); + } + + return Inst(Opcode::Mul64, a, b); +} + U32 IREmitter::And(const U32& a, const U32& b) { return Inst(Opcode::And32, a, b); } diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 24166cfe..da49cac7 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -115,6 +115,7 @@ public: U32U64 Sub(const U32U64& a, const U32U64& b); U32 Mul(const U32& a, const U32& b); U64 Mul(const U64& a, const U64& b); + U32U64 Mul(const U32U64& a, const U32U64& b); U32 And(const U32& a, const U32& b); U32U64 And(const U32U64& a, const U32U64& b); U32 Eor(const U32& a, const U32& b);