Implement CDP, LDC, MCR, MCRR, MRC, MRRC, STC
This commit is contained in:
parent
48693eb6ff
commit
e3bc7d039f
5 changed files with 217 additions and 28 deletions
|
@ -12,6 +12,7 @@ set(SRCS
|
||||||
frontend/translate/translate.cpp
|
frontend/translate/translate.cpp
|
||||||
frontend/translate/translate_arm.cpp
|
frontend/translate/translate_arm.cpp
|
||||||
frontend/translate/translate_arm/branch.cpp
|
frontend/translate/translate_arm/branch.cpp
|
||||||
|
frontend/translate/translate_arm/coprocessor.cpp
|
||||||
frontend/translate/translate_arm/data_processing.cpp
|
frontend/translate/translate_arm/data_processing.cpp
|
||||||
frontend/translate/translate_arm/exception_generating.cpp
|
frontend/translate/translate_arm/exception_generating.cpp
|
||||||
frontend/translate/translate_arm/extension.cpp
|
frontend/translate/translate_arm/extension.cpp
|
||||||
|
|
|
@ -40,20 +40,13 @@ std::vector<ArmMatcher<V>> GetArmDecodeTable() {
|
||||||
INST(&V::arm_BXJ, "BXJ", "cccc000100101111111111110010mmmm"), // v5J
|
INST(&V::arm_BXJ, "BXJ", "cccc000100101111111111110010mmmm"), // v5J
|
||||||
|
|
||||||
// Coprocessor instructions
|
// Coprocessor instructions
|
||||||
INST(&V::arm_CDP, "CDP2", "11111110-------------------1----"), // v5
|
INST(&V::arm_CDP, "CDP", "cccc1110ooooNNNNDDDDppppooo0MMMM"), // v2 (CDP2: v5)
|
||||||
INST(&V::arm_CDP, "CDP", "----1110-------------------0----"), // v2
|
INST(&V::arm_LDC, "LDC", "cccc110pudw1nnnnDDDDppppvvvvvvvv"), // v2 (LDC2: v5)
|
||||||
INST(&V::arm_LDC, "LDC2", "1111110----1--------------------"), // v5
|
INST(&V::arm_MCR, "MCR", "cccc1110ooo0NNNNttttppppooo1MMMM"), // v2 (MCR2: v5)
|
||||||
INST(&V::arm_LDC, "LDC", "----110----1--------------------"), // v2
|
INST(&V::arm_MCRR, "MCRR", "cccc11000100uuuuttttppppooooMMMM"), // v5E (MCRR2: v6)
|
||||||
INST(&V::arm_MCR, "MCR2", "11111110---0---------------1----"), // v5
|
INST(&V::arm_MRC, "MRC", "cccc1110ooo1NNNNttttppppooo1MMMM"), // v2 (MRC2: v5)
|
||||||
INST(&V::arm_MCR, "MCR", "----1110---0---------------1----"), // v2
|
INST(&V::arm_MRRC, "MRRC", "cccc11000101uuuuttttppppooooMMMM"), // v5E (MRRC2: v6)
|
||||||
INST(&V::arm_MCRR, "MCRR2", "111111000100--------------------"), // v6
|
INST(&V::arm_STC, "STC", "cccc110pudw0nnnnDDDDppppvvvvvvvv"), // v2 (STC2: v5)
|
||||||
INST(&V::arm_MCRR, "MCRR", "----11000100--------------------"), // v5E
|
|
||||||
INST(&V::arm_MRC, "MRC2", "11111110---1---------------1----"), // v5
|
|
||||||
INST(&V::arm_MRC, "MRC", "----1110---1---------------1----"), // v2
|
|
||||||
INST(&V::arm_MRRC, "MRRC2", "111111000101--------------------"), // v6
|
|
||||||
INST(&V::arm_MRRC, "MRRC", "----11000101--------------------"), // v5E
|
|
||||||
INST(&V::arm_STC, "STC2", "1111110----0--------------------"), // v5
|
|
||||||
INST(&V::arm_STC, "STC", "----110----0--------------------"), // v2
|
|
||||||
|
|
||||||
// Data Processing instructions
|
// Data Processing instructions
|
||||||
INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
|
|
|
@ -103,6 +103,10 @@ public:
|
||||||
return fmt::format("{}{}", dp_operation ? 'd' : 's', reg_num + 1);
|
return fmt::format("{}{}", dp_operation ? 'd' : 's', reg_num + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CondOrTwo(Cond cond) {
|
||||||
|
return cond == Cond::NV ? "2" : CondToString(cond);
|
||||||
|
}
|
||||||
|
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
std::string arm_B(Cond cond, Imm24 imm24) {
|
std::string arm_B(Cond cond, Imm24 imm24) {
|
||||||
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8;
|
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8;
|
||||||
|
@ -127,13 +131,53 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coprocessor instructions
|
// Coprocessor instructions
|
||||||
std::string arm_CDP() { return "cdp <unimplemented>"; }
|
std::string arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm) {
|
||||||
std::string arm_LDC() { return "ldc <unimplemented>"; }
|
return fmt::format("cdp{} p{}, #{}, {}, {}, {}, #{}", CondToString(cond), coproc_no, opc1, CRd, CRn, CRm, opc2);
|
||||||
std::string arm_MCR() { return "mcr <unimplemented>"; }
|
}
|
||||||
std::string arm_MCRR() { return "mcrr <unimplemented>"; }
|
|
||||||
std::string arm_MRC() { return "mrc <unimplemented>"; }
|
std::string arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
|
||||||
std::string arm_MRRC() { return "mrrc <unimplemented>"; }
|
const u32 imm32 = static_cast<u32>(imm8) << 2;
|
||||||
std::string arm_STC() { return "stc <unimplemented>"; }
|
if (!p && !u && !d && !w)
|
||||||
|
return "<undefined>";
|
||||||
|
if (p)
|
||||||
|
return fmt::format("ldc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32, w ? "!" : "");
|
||||||
|
if (!p && w)
|
||||||
|
return fmt::format("ldc{}{} {}, {}, [{}], #{}{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32);
|
||||||
|
if (!p && !w && u)
|
||||||
|
return fmt::format("ldc{}{} {}, {}, [{}], {}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, imm8);
|
||||||
|
UNREACHABLE();
|
||||||
|
return "<internal error>";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string arm_MCR(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm) {
|
||||||
|
return fmt::format("mcr{} p{}, #{}, {}, {}, {}, #{}", CondOrTwo(cond), coproc_no, opc1, t, CRn, CRm, opc2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string arm_MCRR(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm) {
|
||||||
|
return fmt::format("mcr{} p{}, #{}, {}, {}, {}", CondOrTwo(cond), coproc_no, opc, t, t2, CRm);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm) {
|
||||||
|
return fmt::format("mrc{} p{}, #{}, {}, {}, {}, #{}", CondOrTwo(cond), coproc_no, opc1, t, CRn, CRm, opc2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm) {
|
||||||
|
return fmt::format("mrrc{} p{}, #{}, {}, {}, {}", CondOrTwo(cond), coproc_no, opc, t, t2, CRm);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
|
||||||
|
const u32 imm32 = static_cast<u32>(imm8) << 2;
|
||||||
|
if (!p && !u && !d && !w)
|
||||||
|
return "<undefined>";
|
||||||
|
if (p)
|
||||||
|
return fmt::format("stc{}{} {}, {}, [{}, #{}{}]{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32, w ? "!" : "");
|
||||||
|
if (!p && w)
|
||||||
|
return fmt::format("stc{}{} {}, {}, [{}], #{}{}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, u ? "+" : "-", imm32);
|
||||||
|
if (!p && !w && u)
|
||||||
|
return fmt::format("stc{}{} {}, {}, [{}], {}", d ? "l" : "", CondOrTwo(cond), coproc_no, CRd, n, imm8);
|
||||||
|
UNREACHABLE();
|
||||||
|
return "<internal error>";
|
||||||
|
}
|
||||||
|
|
||||||
// Data processing instructions
|
// Data processing instructions
|
||||||
std::string arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
std::string arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
|
|
151
src/frontend/translate/translate_arm/coprocessor.cpp
Normal file
151
src/frontend/translate/translate_arm/coprocessor.cpp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 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 "translate_arm.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
namespace Arm {
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm) {
|
||||||
|
if ((coproc_no & 0b1110) == 0b1010)
|
||||||
|
return arm_UDF();
|
||||||
|
|
||||||
|
const bool two = cond == Cond::NV;
|
||||||
|
|
||||||
|
// CDP{2} <coproc_no>, #<opc1>, <CRd>, <CRn>, <CRm>, #<opc2>
|
||||||
|
if (two || ConditionPassed(cond)) {
|
||||||
|
ir.CoprocInternalOperation(coproc_no, two, opc1, CRd, CRn, CRm, opc2);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
|
||||||
|
if (!p && !u && !d && !w)
|
||||||
|
return arm_UDF();
|
||||||
|
if ((coproc_no & 0b1110) == 0b1010)
|
||||||
|
return arm_UDF();
|
||||||
|
|
||||||
|
const bool two = cond == Cond::NV;
|
||||||
|
const u32 imm32 = static_cast<u8>(imm8) << 2;
|
||||||
|
const bool index = p;
|
||||||
|
const bool add = u;
|
||||||
|
const bool wback = w;
|
||||||
|
const bool has_option = !p & !w & u;
|
||||||
|
|
||||||
|
// LDC{2}{L} <coproc_no>, <CRd>, [<Rn>, #+/-<imm32>]{!}
|
||||||
|
// LDC{2}{L} <coproc_no>, <CRd>, [<Rn>], #+/-<imm32>
|
||||||
|
// LDC{2}{L} <coproc_no>, <CRd>, [<Rn>], <imm8>
|
||||||
|
if (two || ConditionPassed(cond)) {
|
||||||
|
auto reg_n = ir.GetRegister(n);
|
||||||
|
auto offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
|
||||||
|
auto address = index ? offset_address : reg_n;
|
||||||
|
ir.CoprocLoadWords(coproc_no, two, d, CRd, address, has_option, imm8);
|
||||||
|
if (wback) {
|
||||||
|
ir.SetRegister(n, offset_address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_MCR(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm) {
|
||||||
|
if ((coproc_no & 0b1110) == 0b1010)
|
||||||
|
return arm_UDF();
|
||||||
|
if (t == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
const bool two = cond == Cond::NV;
|
||||||
|
|
||||||
|
// MCR{2} <coproc_no>, #<opc1>, <Rt>, <CRn>, <CRm>, #<opc2>
|
||||||
|
if (two || ConditionPassed(cond)) {
|
||||||
|
ir.CoprocSendOneWord(coproc_no, two, opc1, CRn, CRm, opc2, ir.GetRegister(t));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_MCRR(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm) {
|
||||||
|
if ((coproc_no & 0b1110) == 0b1010)
|
||||||
|
return arm_UDF();
|
||||||
|
if (t == Reg::PC || t2 == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
const bool two = cond == Cond::NV;
|
||||||
|
|
||||||
|
// MCRR{2} <coproc_no>, #<opc>, <Rt>, <Rt2>, <CRm>
|
||||||
|
if (two || ConditionPassed(cond)) {
|
||||||
|
ir.CoprocSendTwoWords(coproc_no, two, opc, CRm, ir.GetRegister(t), ir.GetRegister(t2));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm) {
|
||||||
|
if ((coproc_no & 0b1110) == 0b1010)
|
||||||
|
return arm_UDF();
|
||||||
|
|
||||||
|
const bool two = cond == Cond::NV;
|
||||||
|
|
||||||
|
// MRC{2} <coproc_no>, #<opc1>, <Rt>, <CRn>, <CRm>, #<opc2>
|
||||||
|
if (two || ConditionPassed(cond)) {
|
||||||
|
auto word = ir.CoprocGetOneWord(coproc_no, two, opc1, CRn, CRm, opc2);
|
||||||
|
if (t != Reg::PC) {
|
||||||
|
ir.SetRegister(t, word);
|
||||||
|
} else {
|
||||||
|
auto old_cpsr = ir.And(ir.GetCpsr(), ir.Imm32(0x0FFFFFFF));
|
||||||
|
auto new_cpsr_nzcv = ir.And(word, ir.Imm32(0xF0000000));
|
||||||
|
ir.SetCpsr(ir.Or(old_cpsr, new_cpsr_nzcv));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArmTranslatorVisitor::arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm) {
|
||||||
|
if ((coproc_no & 0b1110) == 0b1010)
|
||||||
|
return arm_UDF();
|
||||||
|
if (t == Reg::PC || t2 == Reg::PC || t == t2)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
const bool two = cond == Cond::NV;
|
||||||
|
|
||||||
|
// MRRC{2} <coproc_no>, #<opc>, <Rt>, <Rt2>, <CRm>
|
||||||
|
if (two || ConditionPassed(cond)) {
|
||||||
|
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 ArmTranslatorVisitor::arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8) {
|
||||||
|
if ((coproc_no & 0b1110) == 0b1010)
|
||||||
|
return arm_UDF();
|
||||||
|
if (!p && !u && !d && !w)
|
||||||
|
return arm_UDF();
|
||||||
|
if (n == Reg::PC && w)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
|
||||||
|
const bool two = cond == Cond::NV;
|
||||||
|
const u32 imm32 = static_cast<u8>(imm8) << 2;
|
||||||
|
const bool index = p;
|
||||||
|
const bool add = u;
|
||||||
|
const bool wback = w;
|
||||||
|
const bool has_option = !p & !w & u;
|
||||||
|
|
||||||
|
// STC{2}{L} <coproc>, <CRd>, [<Rn>, #+/-<imm32>]{!}
|
||||||
|
// STC{2}{L} <coproc>, <CRd>, [<Rn>], #+/-<imm32>
|
||||||
|
// STC{2}{L} <coproc>, <CRd>, [<Rn>], <imm8>
|
||||||
|
if (two || ConditionPassed(cond)) {
|
||||||
|
auto reg_n = ir.GetRegister(n);
|
||||||
|
auto offset_address = add ? ir.Add(reg_n, ir.Imm32(imm32)) : ir.Sub(reg_n, ir.Imm32(imm32));
|
||||||
|
auto address = index ? offset_address : reg_n;
|
||||||
|
ir.CoprocStoreWords(coproc_no, two, d, CRd, address, has_option, imm8);
|
||||||
|
if (wback) {
|
||||||
|
ir.SetRegister(n, offset_address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Arm
|
||||||
|
} // namespace Dynarmic
|
|
@ -75,13 +75,13 @@ struct ArmTranslatorVisitor final {
|
||||||
bool arm_BXJ(Cond cond, Reg m);
|
bool arm_BXJ(Cond cond, Reg m);
|
||||||
|
|
||||||
// Coprocessor instructions
|
// Coprocessor instructions
|
||||||
bool arm_CDP() { return InterpretThisInstruction(); }
|
bool arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
bool arm_LDC() { return InterpretThisInstruction(); }
|
bool arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8);
|
||||||
bool arm_MCR() { return InterpretThisInstruction(); }
|
bool arm_MCR(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
bool arm_MCRR() { return InterpretThisInstruction(); }
|
bool arm_MCRR(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
||||||
bool arm_MRC() { return InterpretThisInstruction(); }
|
bool arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
bool arm_MRRC() { return InterpretThisInstruction(); }
|
bool arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
||||||
bool arm_STC() { return InterpretThisInstruction(); }
|
bool arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm8 imm8);
|
||||||
|
|
||||||
// Data processing instructions
|
// Data processing instructions
|
||||||
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
||||||
|
|
Loading…
Reference in a new issue