From b93ae62acf850b3a5fb37e55053ae55aad5c000b Mon Sep 17 00:00:00 2001 From: MerryMage Date: Thu, 13 May 2021 18:02:38 +0100 Subject: [PATCH] thumb32: Add coprocessor instructions --- src/CMakeLists.txt | 1 + src/frontend/A32/decoder/thumb32.inc | 23 ++---- .../translate/impl/thumb32_coprocessor.cpp | 75 +++++++++++++++++++ src/frontend/A32/translate/impl/translate.h | 9 +++ tests/A32/fuzz_arm.cpp | 3 + 5 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 src/frontend/A32/translate/impl/thumb32_coprocessor.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c4faec44..e6bf1c15 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -157,6 +157,7 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/translate/impl/thumb16.cpp frontend/A32/translate/impl/thumb32_branch.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_plain_binary_immediate.cpp frontend/A32/translate/impl/thumb32_data_processing_register.cpp diff --git a/src/frontend/A32/decoder/thumb32.inc b/src/frontend/A32/decoder/thumb32.inc index d35771f3..33497108 100644 --- a/src/frontend/A32/decoder/thumb32.inc +++ b/src/frontend/A32/decoder/thumb32.inc @@ -281,19 +281,10 @@ INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhh INST(thumb32_UMAAL, "UMAAL", "111110111110nnnnllllhhhh0110mmmm") // Coprocessor -//INST(thumb32_MCRR2, "MCRR2", "111111000100--------------------") -//INST(thumb32_MCRR, "MCRR", "111011000100--------------------") -//INST(thumb32_STC2, "STC2", "1111110----0--------------------") -//INST(thumb32_STC, "STC", "1110110----0--------------------") -//INST(thumb32_MRRC2, "MRRC2", "111111000101--------------------") -//INST(thumb32_MRRC, "MRRC", "111011000101--------------------") -//INST(thumb32_LDC2_lit, "LDC2 (lit)", "1111110----11111----------------") -//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----") +INST(thumb32_MCRR, "MCRR", "111o11000100uuuuttttppppooooMMMM") +INST(thumb32_MRRC, "MRRC", "111o11000101uuuuttttppppooooMMMM") +INST(thumb32_STC, "STC", "111o110pudw0nnnnDDDDppppvvvvvvvv") +INST(thumb32_LDC, "LDC", "111o110pudw1nnnnDDDDppppvvvvvvvv") +INST(thumb32_CDP, "CDP", "111o1110ooooNNNNDDDDppppooo0MMMM") +INST(thumb32_MCR, "MCR", "111o1110ooo0NNNNttttppppooo1MMMM") +INST(thumb32_MRC, "MRC", "111o1110ooo1NNNNttttppppooo1MMMM") diff --git a/src/frontend/A32/translate/impl/thumb32_coprocessor.cpp b/src/frontend/A32/translate/impl/thumb32_coprocessor.cpp new file mode 100644 index 00000000..e7ad603e --- /dev/null +++ b/src/frontend/A32/translate/impl/thumb32_coprocessor.cpp @@ -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()); + 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()); + 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 diff --git a/src/frontend/A32/translate/impl/translate.h b/src/frontend/A32/translate/impl/translate.h index 6cdeac02..2f67ad4b 100644 --- a/src/frontend/A32/translate/impl/translate.h +++ b/src/frontend/A32/translate/impl/translate.h @@ -740,6 +740,15 @@ struct TranslatorVisitor final { bool thumb32_UHSUB8(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 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); diff --git a/tests/A32/fuzz_arm.cpp b/tests/A32/fuzz_arm.cpp index 8acac3f8..9a73a32d 100644 --- a/tests/A32/fuzz_arm.cpp +++ b/tests/A32/fuzz_arm.cpp @@ -200,6 +200,9 @@ std::vector GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s "vfp_VCVT_from_fixed", "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. + + // Coprocessor + "thumb32_CDP", "thumb32_LDC", "thumb32_MCR", "thumb32_MCRR", "thumb32_MRC", "thumb32_MRRC", "thumb32_STC", }; for (const auto& [fn, bitstring] : list) {