thumb32: Add coprocessor instructions

This commit is contained in:
MerryMage 2021-05-13 18:02:38 +01:00
parent 5ebe11c329
commit b93ae62acf
5 changed files with 95 additions and 16 deletions

View file

@ -157,6 +157,7 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS)
frontend/A32/translate/impl/thumb16.cpp frontend/A32/translate/impl/thumb16.cpp
frontend/A32/translate/impl/thumb32_branch.cpp frontend/A32/translate/impl/thumb32_branch.cpp
frontend/A32/translate/impl/thumb32_control.cpp frontend/A32/translate/impl/thumb32_control.cpp
frontend/A32/translate/impl/thumb32_coprocessor.cpp
frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp frontend/A32/translate/impl/thumb32_data_processing_modified_immediate.cpp
frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp frontend/A32/translate/impl/thumb32_data_processing_plain_binary_immediate.cpp
frontend/A32/translate/impl/thumb32_data_processing_register.cpp frontend/A32/translate/impl/thumb32_data_processing_register.cpp

View file

@ -281,19 +281,10 @@ INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhh
INST(thumb32_UMAAL, "UMAAL", "111110111110nnnnllllhhhh0110mmmm") INST(thumb32_UMAAL, "UMAAL", "111110111110nnnnllllhhhh0110mmmm")
// Coprocessor // Coprocessor
//INST(thumb32_MCRR2, "MCRR2", "111111000100--------------------") INST(thumb32_MCRR, "MCRR", "111o11000100uuuuttttppppooooMMMM")
//INST(thumb32_MCRR, "MCRR", "111011000100--------------------") INST(thumb32_MRRC, "MRRC", "111o11000101uuuuttttppppooooMMMM")
//INST(thumb32_STC2, "STC2", "1111110----0--------------------") INST(thumb32_STC, "STC", "111o110pudw0nnnnDDDDppppvvvvvvvv")
//INST(thumb32_STC, "STC", "1110110----0--------------------") INST(thumb32_LDC, "LDC", "111o110pudw1nnnnDDDDppppvvvvvvvv")
//INST(thumb32_MRRC2, "MRRC2", "111111000101--------------------") INST(thumb32_CDP, "CDP", "111o1110ooooNNNNDDDDppppooo0MMMM")
//INST(thumb32_MRRC, "MRRC", "111011000101--------------------") INST(thumb32_MCR, "MCR", "111o1110ooo0NNNNttttppppooo1MMMM")
//INST(thumb32_LDC2_lit, "LDC2 (lit)", "1111110----11111----------------") INST(thumb32_MRC, "MRC", "111o1110ooo1NNNNttttppppooo1MMMM")
//INST(thumb32_LDC_lit, "LDC (lit)", "1110110----11111----------------")
//INST(thumb32_LDC2_imm, "LDC2 (imm)", "1111110----1--------------------")
//INST(thumb32_LDC_imm, "LDC (imm)", "1110110----1--------------------")
//INST(thumb32_CDP2, "CDP2", "11111110-------------------0----")
//INST(thumb32_CDP, "CDP", "11101110-------------------0----")
//INST(thumb32_MCR2, "MCR2", "11111110---0---------------1----")
//INST(thumb32_MCR, "MCR", "11101110---0---------------1----")
//INST(thumb32_MRC2, "MRC2", "11111110---1---------------1----")
//INST(thumb32_MRC, "MRC", "11101110---1---------------1----")

View file

@ -0,0 +1,75 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2021 MerryMage
* SPDX-License-Identifier: 0BSD
*/
#include "frontend/A32/translate/impl/translate.h"
namespace Dynarmic::A32 {
bool TranslatorVisitor::thumb32_MCRR(bool two, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm) {
ir.CoprocSendTwoWords(coproc_no, two, opc, CRm, ir.GetRegister(t), ir.GetRegister(t2));
return true;
}
bool TranslatorVisitor::thumb32_MRRC(bool two, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm) {
const auto two_words = ir.CoprocGetTwoWords(coproc_no, two, opc, CRm);
ir.SetRegister(t, ir.LeastSignificantWord(two_words));
ir.SetRegister(t2, ir.MostSignificantWord(two_words).result);
return true;
}
bool TranslatorVisitor::thumb32_STC(bool two, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
const u32 imm32 = imm8.ZeroExtend() << 2;
const bool index = p;
const bool add = u;
const bool wback = w;
const bool has_option = !p && !w && u;
const IR::U32 reg_n = ir.GetRegister(n);
const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
const IR::U32 address = index ? offset_address : reg_n;
ir.CoprocStoreWords(coproc_no, two, d, CRd, address, has_option, imm8.ZeroExtend<u8>());
if (wback) {
ir.SetRegister(n, offset_address);
}
return true;
}
bool TranslatorVisitor::thumb32_LDC(bool two, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8) {
const u32 imm32 = imm8.ZeroExtend() << 2;
const bool index = p;
const bool add = u;
const bool wback = w;
const bool has_option = !p && !w && u;
const IR::U32 reg_n = ir.GetRegister(n);
const IR::U32 offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
const IR::U32 address = index ? offset_address : reg_n;
ir.CoprocLoadWords(coproc_no, two, d, CRd, address, has_option, imm8.ZeroExtend<u8>());
if (wback) {
ir.SetRegister(n, offset_address);
}
return true;
}
bool TranslatorVisitor::thumb32_CDP(bool two, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm) {
ir.CoprocInternalOperation(coproc_no, two, opc1, CRd, CRn, CRm, opc2);
return true;
}
bool TranslatorVisitor::thumb32_MCR(bool two, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm) {
ir.CoprocSendOneWord(coproc_no, two, opc1, CRn, CRm, opc2, ir.GetRegister(t));
return true;
}
bool TranslatorVisitor::thumb32_MRC(bool two, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm) {
const auto word = ir.CoprocGetOneWord(coproc_no, two, opc1, CRn, CRm, opc2);
if (t != Reg::PC) {
ir.SetRegister(t, word);
} else {
const auto new_cpsr_nzcv = ir.And(word, ir.Imm32(0xF0000000));
ir.SetCpsrNZCV(new_cpsr_nzcv);
}
return true;
}
} // namespace Dynarmic::A32

View file

@ -740,6 +740,15 @@ struct TranslatorVisitor final {
bool thumb32_UHSUB8(Reg n, Reg d, Reg m); bool thumb32_UHSUB8(Reg n, Reg d, Reg m);
bool thumb32_UHSUB16(Reg n, Reg d, Reg m); bool thumb32_UHSUB16(Reg n, Reg d, Reg m);
// thumb32 coprocessor insturctions
bool thumb32_MCRR(bool two, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
bool thumb32_MRRC(bool two, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
bool thumb32_STC(bool two, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
bool thumb32_LDC(bool two, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
bool thumb32_CDP(bool two, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm);
bool thumb32_MCR(bool two, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
bool thumb32_MRC(bool two, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
// Floating-point three-register data processing instructions // Floating-point three-register data processing instructions
bool vfp_VADD(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); bool vfp_VADD(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
bool vfp_VSUB(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm); bool vfp_VSUB(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);

View file

@ -200,6 +200,9 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
"vfp_VCVT_from_fixed", "vfp_VCVT_from_fixed",
"asimd_VRECPS", // Unicorn does not fuse the multiply and subtraction, resulting in being off by 1ULP. "asimd_VRECPS", // Unicorn does not fuse the multiply and subtraction, resulting in being off by 1ULP.
"asimd_VRSQRTS", // Unicorn does not fuse the multiply and subtraction, resulting in being off by 1ULP. "asimd_VRSQRTS", // Unicorn does not fuse the multiply and subtraction, resulting in being off by 1ULP.
// Coprocessor
"thumb32_CDP", "thumb32_LDC", "thumb32_MCR", "thumb32_MCRR", "thumb32_MRC", "thumb32_MRRC", "thumb32_STC",
}; };
for (const auto& [fn, bitstring] : list) { for (const auto& [fn, bitstring] : list) {