Frontend/Decoder: 1. Remove member pointer as a template argument. 2. Sort ARM table such that unconditional instructions are on top.
This commit is contained in:
parent
94d5738f62
commit
8ff414ee0e
6 changed files with 188 additions and 153 deletions
|
@ -11,12 +11,12 @@
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
namespace mp {
|
namespace mp {
|
||||||
|
|
||||||
template<typename MemFnT, MemFnT fn>
|
template<typename MemFnT>
|
||||||
struct MemFnInfo;
|
struct MemFnInfo;
|
||||||
|
|
||||||
/// This struct provides information about a member function pointer.
|
/// This struct provides information about a member function pointer.
|
||||||
template<typename T, typename ReturnT, typename ...Args, ReturnT (T::*fn)(Args...)>
|
template<typename T, typename ReturnT, typename ...Args>
|
||||||
struct MemFnInfo<ReturnT (T::*)(Args...), fn> {
|
struct MemFnInfo<ReturnT (T::*)(Args...)> {
|
||||||
using class_type = T;
|
using class_type = T;
|
||||||
using return_type = ReturnT;
|
using return_type = ReturnT;
|
||||||
static constexpr size_t args_count = sizeof...(Args);
|
static constexpr size_t args_count = sizeof...(Args);
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Arm {
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
struct ArmMatcher {
|
struct ArmMatcher {
|
||||||
using CallRetT = typename mp::MemFnInfo<decltype(&Visitor::arm_UDF), &Visitor::arm_UDF>::return_type;
|
using CallRetT = typename mp::MemFnInfo<decltype(&Visitor::arm_UDF)>::return_type;
|
||||||
|
|
||||||
ArmMatcher(const char* const name, u32 mask, u32 expect, std::function<CallRetT(Visitor&, u32)> fn)
|
ArmMatcher(const char* const name, u32 mask, u32 expect, std::function<CallRetT(Visitor&, u32)> fn)
|
||||||
: name(name), mask(mask), expect(expect), fn(fn) {}
|
: name(name), mask(mask), expect(expect), fn(fn) {}
|
||||||
|
@ -51,41 +51,49 @@ struct ArmMatcher {
|
||||||
return fn(v, instruction);
|
return fn(v, instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GetMask() const {
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetExpect() const {
|
||||||
|
return expect;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* name;
|
const char* name;
|
||||||
u32 mask, expect;
|
u32 mask, expect;
|
||||||
std::function<CallRetT(Visitor&, u32)> fn;
|
std::function<CallRetT(Visitor&, u32)> fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename V>
|
template <typename V>
|
||||||
boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
std::vector<ArmMatcher<V>> GetArmDecodeTable() {
|
||||||
const static std::vector<ArmMatcher<V>> table = {
|
std::vector<ArmMatcher<V>> table = {
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) detail::detail<ArmMatcher, u32, 32>::GetMatcher<decltype(fn), fn>(name, bitstring)
|
#define INST(fn, name, bitstring) detail::detail<ArmMatcher, u32, 32>::GetMatcher<decltype(fn)>(fn, name, bitstring)
|
||||||
|
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
//INST(&V::arm_BLX_imm, "BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv"), // v5
|
INST(&V::arm_BLX_imm, "BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv"), // v5
|
||||||
//INST(&V::arm_BLX_reg, "BLX (reg)", "cccc000100101111111111110011mmmm"), // v5
|
INST(&V::arm_BLX_reg, "BLX (reg)", "cccc000100101111111111110011mmmm"), // v5
|
||||||
INST(&V::arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv"), // all
|
INST(&V::arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv"), // all
|
||||||
INST(&V::arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv"), // all
|
INST(&V::arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv"), // all
|
||||||
INST(&V::arm_BX, "BX", "cccc000100101111111111110001mmmm"), // v4T
|
INST(&V::arm_BX, "BX", "cccc000100101111111111110001mmmm"), // v4T
|
||||||
//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, "CDP2", "11111110-------------------1----"), // v5
|
||||||
//INST(&V::arm_CDP, "CDP", "----1110-------------------0----"), // v2
|
INST(&V::arm_CDP, "CDP", "----1110-------------------0----"), // v2
|
||||||
//INST(&V::arm_LDC, "LDC2", "1111110----1--------------------"), // v5
|
INST(&V::arm_LDC, "LDC2", "1111110----1--------------------"), // v5
|
||||||
//INST(&V::arm_LDC, "LDC", "----110----1--------------------"), // v2
|
INST(&V::arm_LDC, "LDC", "----110----1--------------------"), // v2
|
||||||
//INST(&V::arm_MCR, "MCR2", "----1110---0---------------1----"), // v5
|
INST(&V::arm_MCR, "MCR2", "----1110---0---------------1----"), // v5
|
||||||
//INST(&V::arm_MCR, "MCR", "----1110---0---------------1----"), // v2
|
INST(&V::arm_MCR, "MCR", "----1110---0---------------1----"), // v2
|
||||||
//INST(&V::arm_MCRR, "MCRR2", "111111000100--------------------"), // v6
|
INST(&V::arm_MCRR, "MCRR2", "111111000100--------------------"), // v6
|
||||||
//INST(&V::arm_MCRR, "MCRR", "----11000100--------------------"), // v5E
|
INST(&V::arm_MCRR, "MCRR", "----11000100--------------------"), // v5E
|
||||||
//INST(&V::arm_MRC, "MRC2", "11111110---1---------------1----"), // v5
|
INST(&V::arm_MRC, "MRC2", "11111110---1---------------1----"), // v5
|
||||||
//INST(&V::arm_MRC, "MRC", "----1110---1---------------1----"), // v2
|
INST(&V::arm_MRC, "MRC", "----1110---1---------------1----"), // v2
|
||||||
//INST(&V::arm_MRRC, "MRRC2", "111111000101--------------------"), // v6
|
INST(&V::arm_MRRC, "MRRC2", "111111000101--------------------"), // v6
|
||||||
//INST(&V::arm_MRRC, "MRRC", "----11000101--------------------"), // v5E
|
INST(&V::arm_MRRC, "MRRC", "----11000101--------------------"), // v5E
|
||||||
//INST(&V::arm_STC, "STC2", "1111110----0--------------------"), // v5
|
INST(&V::arm_STC, "STC2", "1111110----0--------------------"), // v5
|
||||||
//INST(&V::arm_STC, "STC", "----110----0--------------------"), // v2
|
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
|
||||||
|
@ -138,7 +146,7 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
INST(&V::arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm"), // all
|
INST(&V::arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm"), // all
|
||||||
|
|
||||||
// Exception Generating instructions
|
// Exception Generating instructions
|
||||||
//INST(&V::arm_BKPT, "BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv"), // v5
|
INST(&V::arm_BKPT, "BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv"), // v5
|
||||||
INST(&V::arm_SVC, "SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv"), // all
|
INST(&V::arm_SVC, "SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv"), // all
|
||||||
INST(&V::arm_UDF, "UDF", "111001111111------------1111----"), // all
|
INST(&V::arm_UDF, "UDF", "111001111111------------1111----"), // all
|
||||||
|
|
||||||
|
@ -157,82 +165,82 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
INST(&V::arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm"), // v6
|
INST(&V::arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm"), // v6
|
||||||
|
|
||||||
// Hint instructions
|
// Hint instructions
|
||||||
//INST(&V::arm_PLD, "PLD", "111101---101----1111------------"), // v5E
|
INST(&V::arm_PLD, "PLD", "111101---101----1111------------"), // v5E
|
||||||
//INST(&V::arm_SEV, "SEV", "----0011001000001111000000000100"), // v6K
|
INST(&V::arm_SEV, "SEV", "----0011001000001111000000000100"), // v6K
|
||||||
//INST(&V::arm_WFE, "WFE", "----0011001000001111000000000010"), // v6K
|
INST(&V::arm_WFE, "WFE", "----0011001000001111000000000010"), // v6K
|
||||||
//INST(&V::arm_WFI, "WFI", "----0011001000001111000000000011"), // v6K
|
INST(&V::arm_WFI, "WFI", "----0011001000001111000000000011"), // v6K
|
||||||
//INST(&V::arm_YIELD, "YIELD", "----0011001000001111000000000001"), // v6K
|
INST(&V::arm_YIELD, "YIELD", "----0011001000001111000000000001"), // v6K
|
||||||
|
|
||||||
// Synchronization Primitive instructions
|
// Synchronization Primitive instructions
|
||||||
//INST(&V::arm_CLREX, "CLREX", "11110101011111111111000000011111"), // v6K
|
INST(&V::arm_CLREX, "CLREX", "11110101011111111111000000011111"), // v6K
|
||||||
//INST(&V::arm_LDREX, "LDREX", "cccc00011001nnnndddd111110011111"), // v6
|
INST(&V::arm_LDREX, "LDREX", "cccc00011001nnnndddd111110011111"), // v6
|
||||||
//INST(&V::arm_LDREXB, "LDREXB", "cccc00011101nnnndddd111110011111"), // v6K
|
INST(&V::arm_LDREXB, "LDREXB", "cccc00011101nnnndddd111110011111"), // v6K
|
||||||
//INST(&V::arm_LDREXD, "LDREXD", "cccc00011011nnnndddd111110011111"), // v6K
|
INST(&V::arm_LDREXD, "LDREXD", "cccc00011011nnnndddd111110011111"), // v6K
|
||||||
//INST(&V::arm_LDREXH, "LDREXH", "cccc00011111nnnndddd111110011111"), // v6K
|
INST(&V::arm_LDREXH, "LDREXH", "cccc00011111nnnndddd111110011111"), // v6K
|
||||||
//INST(&V::arm_STREX, "STREX", "cccc00011000nnnndddd11111001mmmm"), // v6
|
INST(&V::arm_STREX, "STREX", "cccc00011000nnnndddd11111001mmmm"), // v6
|
||||||
//INST(&V::arm_STREXB, "STREXB", "cccc00011100nnnndddd11111001mmmm"), // v6K
|
INST(&V::arm_STREXB, "STREXB", "cccc00011100nnnndddd11111001mmmm"), // v6K
|
||||||
//INST(&V::arm_STREXD, "STREXD", "cccc00011010nnnndddd11111001mmmm"), // v6K
|
INST(&V::arm_STREXD, "STREXD", "cccc00011010nnnndddd11111001mmmm"), // v6K
|
||||||
//INST(&V::arm_STREXH, "STREXH", "cccc00011110nnnndddd11111001mmmm"), // v6K
|
INST(&V::arm_STREXH, "STREXH", "cccc00011110nnnndddd11111001mmmm"), // v6K
|
||||||
//INST(&V::arm_SWP, "SWP", "cccc00010000nnnndddd00001001mmmm"), // v2S (v6: Deprecated)
|
INST(&V::arm_SWP, "SWP", "cccc00010000nnnndddd00001001mmmm"), // v2S (v6: Deprecated)
|
||||||
//INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnndddd00001001mmmm"), // v2S (v6: Deprecated)
|
INST(&V::arm_SWPB, "SWPB", "cccc00010100nnnndddd00001001mmmm"), // v2S (v6: Deprecated)
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store instructions
|
||||||
INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnddddvvvvvvvvvvvv"),
|
||||||
INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnddddvvvvvrr0mmmm"),
|
||||||
INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnddddvvvvvvvvvvvv"),
|
||||||
INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnddddvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_LDRBT, "LDRBT (A1)", "cccc0100u111nnnnttttvvvvvvvvvvvv"),
|
INST(&V::arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------"),
|
||||||
//INST(&V::arm_LDRBT, "LDRBT (A2)", "cccc0110u111nnnnttttvvvvvrr0mmmm"),
|
INST(&V::arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----"),
|
||||||
INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E
|
INST(&V::arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnddddvvvv1101vvvv"), // v5E
|
||||||
INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E
|
INST(&V::arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnndddd00001101mmmm"), // v5E
|
||||||
INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"),
|
INST(&V::arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnddddvvvv1011vvvv"),
|
||||||
INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"),
|
INST(&V::arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnndddd00001011mmmm"),
|
||||||
//INST(&V::arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----"),
|
INST(&V::arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----"),
|
||||||
//INST(&V::arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----"),
|
INST(&V::arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----"),
|
||||||
//INST(&V::arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnddddvvvv1101vvvv"),
|
INST(&V::arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnddddvvvv1101vvvv"),
|
||||||
//INST(&V::arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnndddd00001101mmmm"),
|
INST(&V::arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnndddd00001101mmmm"),
|
||||||
//INST(&V::arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----"),
|
INST(&V::arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----"),
|
||||||
//INST(&V::arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----"),
|
INST(&V::arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----"),
|
||||||
//INST(&V::arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnddddvvvv1111vvvv"),
|
INST(&V::arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnddddvvvv1111vvvv"),
|
||||||
//INST(&V::arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnndddd00001111mmmm"),
|
INST(&V::arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnndddd00001111mmmm"),
|
||||||
//INST(&V::arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----"),
|
INST(&V::arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----"),
|
||||||
//INST(&V::arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----"),
|
INST(&V::arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----"),
|
||||||
//INST(&V::arm_LDRT, "LDRT (A1)", "cccc0100u011nnnnttttvvvvvvvvvvvv"),
|
INST(&V::arm_LDRT, "LDRT (A1)", "----0100-011--------------------"),
|
||||||
//INST(&V::arm_LDRT, "LDRT (A2)", "cccc0110u011nnnnttttvvvvvrr0mmmm"),
|
INST(&V::arm_LDRT, "LDRT (A2)", "----0110-011---------------0----"),
|
||||||
INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnddddvvvvvvvvvvvv"),
|
||||||
INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnddddvvvvvrr0mmmm"),
|
||||||
INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"),
|
INST(&V::arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnddddvvvvvvvvvvvv"),
|
||||||
INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"),
|
INST(&V::arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnddddvvvvvrr0mmmm"),
|
||||||
//INST(&V::arm_STRBT, "STRBT (A1)", "cccc0100u110nnnnttttvvvvvvvvvvvv"),
|
INST(&V::arm_STRBT, "STRBT (A1)", "----0100-110--------------------"),
|
||||||
//INST(&V::arm_STRBT, "STRBT (A2)", "cccc0110u110nnnnttttvvvvvrr0mmmm"),
|
INST(&V::arm_STRBT, "STRBT (A2)", "----0110-110---------------0----"),
|
||||||
INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E
|
INST(&V::arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnddddvvvv1111vvvv"), // v5E
|
||||||
INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E
|
INST(&V::arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnndddd00001111mmmm"), // v5E
|
||||||
INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"),
|
INST(&V::arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnddddvvvv1011vvvv"),
|
||||||
INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnndddd00001011mmmm"),
|
INST(&V::arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnndddd00001011mmmm"),
|
||||||
//INST(&V::arm_STRHT, "STRHT (A1)", "----0000-110------------1011----"),
|
INST(&V::arm_STRHT, "STRHT (A1)", "----0000-110------------1011----"),
|
||||||
//INST(&V::arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----"),
|
INST(&V::arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----"),
|
||||||
//INST(&V::arm_STRT, "STRT (A1)", "cccc0100u010nnnnttttvvvvvvvvvvvv"),
|
INST(&V::arm_STRT, "STRT (A1)", "----0100-010--------------------"),
|
||||||
//INST(&V::arm_STRT, "STRT (A2)", "cccc0110u010nnnnttttvvvvvrr0mmmm"),
|
INST(&V::arm_STRT, "STRT (A2)", "----0110-010---------------0----"),
|
||||||
|
|
||||||
// Load/Store Multiple instructions
|
// Load/Store Multiple instructions
|
||||||
//INST(&V::arm_LDM, "LDM", "cccc100pu0w1nnnnxxxxxxxxxxxxxxxx"), // all
|
INST(&V::arm_LDM, "LDM", "cccc100pu0w1nnnnxxxxxxxxxxxxxxxx"), // all
|
||||||
//INST(&V::arm_LDM_usr, "LDM (usr reg)", "----100--101--------------------"), // all
|
INST(&V::arm_LDM_usr, "LDM (usr reg)", "----100--101--------------------"), // all
|
||||||
//INST(&V::arm_LDM_eret, "LDM (exce ret)", "----100--1-1----1---------------"), // all
|
INST(&V::arm_LDM_eret, "LDM (exce ret)", "----100--1-1----1---------------"), // all
|
||||||
//INST(&V::arm_STM, "STM", "cccc100pu0w0nnnnxxxxxxxxxxxxxxxx"), // all
|
INST(&V::arm_STM, "STM", "cccc100pu0w0nnnnxxxxxxxxxxxxxxxx"), // all
|
||||||
//INST(&V::arm_STM_usr, "STM (usr reg)", "----100--100--------------------"), // all
|
INST(&V::arm_STM_usr, "STM (usr reg)", "----100--100--------------------"), // all
|
||||||
|
|
||||||
// Miscellaneous instructions
|
// Miscellaneous instructions
|
||||||
//INST(&V::arm_CLZ, "CLZ", "cccc000101101111dddd11110001mmmm"), // v5
|
INST(&V::arm_CLZ, "CLZ", "cccc000101101111dddd11110001mmmm"), // v5
|
||||||
//INST(&V::arm_NOP, "NOP", "----001100100000111100000000----"), // v6K
|
INST(&V::arm_NOP, "NOP", "----001100100000111100000000----"), // v6K
|
||||||
//INST(&V::arm_SEL, "SEL", "cccc01101000nnnndddd11111011mmmm"), // v6
|
INST(&V::arm_SEL, "SEL", "cccc01101000nnnndddd11111011mmmm"), // v6
|
||||||
|
|
||||||
// Unsigned Sum of Absolute Differences instructions
|
// Unsigned Sum of Absolute Differences instructions
|
||||||
//INST(&V::arm_USAD8, "USAD8", "cccc01111000dddd1111mmmm0001nnnn"), // v6
|
INST(&V::arm_USAD8, "USAD8", "cccc01111000dddd1111mmmm0001nnnn"), // v6
|
||||||
//INST(&V::arm_USADA8, "USADA8", "cccc01111000ddddaaaammmm0001nnnn"), // v6
|
INST(&V::arm_USADA8, "USADA8", "cccc01111000ddddaaaammmm0001nnnn"), // v6
|
||||||
|
|
||||||
// Packing instructions
|
// Packing instructions
|
||||||
//INST(&V::arm_PKHBT, "PKHBT", "cccc01101000nnnnddddvvvvv001mmmm"), // v6K
|
INST(&V::arm_PKHBT, "PKHBT", "cccc01101000nnnnddddvvvvv001mmmm"), // v6K
|
||||||
//INST(&V::arm_PKHTB, "PKHTB", "cccc01101000nnnnddddvvvvv101mmmm"), // v6K
|
INST(&V::arm_PKHTB, "PKHTB", "cccc01101000nnnnddddvvvvv101mmmm"), // v6K
|
||||||
|
|
||||||
// Reversal instructions
|
// Reversal instructions
|
||||||
INST(&V::arm_REV, "REV", "cccc011010111111dddd11110011mmmm"), // v6
|
INST(&V::arm_REV, "REV", "cccc011010111111dddd11110011mmmm"), // v6
|
||||||
|
@ -240,10 +248,10 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
INST(&V::arm_REVSH, "REVSH", "cccc011011111111dddd11111011mmmm"), // v6
|
INST(&V::arm_REVSH, "REVSH", "cccc011011111111dddd11111011mmmm"), // v6
|
||||||
|
|
||||||
// Saturation instructions
|
// Saturation instructions
|
||||||
//INST(&V::arm_SSAT, "SSAT", "cccc0110101vvvvvddddvvvvvr01nnnn"), // v6
|
INST(&V::arm_SSAT, "SSAT", "cccc0110101vvvvvddddvvvvvr01nnnn"), // v6
|
||||||
//INST(&V::arm_SSAT16, "SSAT16", "cccc01101010vvvvdddd11110011nnnn"), // v6
|
INST(&V::arm_SSAT16, "SSAT16", "cccc01101010vvvvdddd11110011nnnn"), // v6
|
||||||
//INST(&V::arm_USAT, "USAT", "cccc0110111vvvvvddddvvvvvr01nnnn"), // v6
|
INST(&V::arm_USAT, "USAT", "cccc0110111vvvvvddddvvvvvr01nnnn"), // v6
|
||||||
//INST(&V::arm_USAT16, "USAT16", "cccc01101110vvvvdddd11110011nnnn"), // v6
|
INST(&V::arm_USAT16, "USAT16", "cccc01101110vvvvdddd11110011nnnn"), // v6
|
||||||
|
|
||||||
// Multiply (Normal) instructions
|
// Multiply (Normal) instructions
|
||||||
INST(&V::arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn"), // v2
|
INST(&V::arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn"), // v2
|
||||||
|
@ -257,87 +265,96 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
INST(&V::arm_UMULL, "UMULL", "cccc0000100Sddddaaaammmm1001nnnn"), // v3M
|
INST(&V::arm_UMULL, "UMULL", "cccc0000100Sddddaaaammmm1001nnnn"), // v3M
|
||||||
|
|
||||||
// Multiply (Halfword) instructions
|
// Multiply (Halfword) instructions
|
||||||
//INST(&V::arm_SMLALxy, "SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn"), // v5xP
|
INST(&V::arm_SMLALxy, "SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn"), // v5xP
|
||||||
//INST(&V::arm_SMLAxy, "SMLAXY", "cccc00010000ddddaaaammmm1xy0nnnn"), // v5xP
|
INST(&V::arm_SMLAxy, "SMLAXY", "cccc00010000ddddaaaammmm1xy0nnnn"), // v5xP
|
||||||
//INST(&V::arm_SMULxy, "SMULXY", "cccc00010110dddd0000mmmm1xy0nnnn"), // v5xP
|
INST(&V::arm_SMULxy, "SMULXY", "cccc00010110dddd0000mmmm1xy0nnnn"), // v5xP
|
||||||
|
|
||||||
// Multiply (Word by Halfword) instructions
|
// Multiply (Word by Halfword) instructions
|
||||||
//INST(&V::arm_SMLAWy, "SMLAWY", "cccc00010010ddddaaaammmm1y00nnnn"), // v5xP
|
INST(&V::arm_SMLAWy, "SMLAWY", "cccc00010010ddddaaaammmm1y00nnnn"), // v5xP
|
||||||
//INST(&V::arm_SMULWy, "SMULWY", "cccc00010010dddd0000mmmm1y10nnnn"), // v5xP
|
INST(&V::arm_SMULWy, "SMULWY", "cccc00010010dddd0000mmmm1y10nnnn"), // v5xP
|
||||||
|
|
||||||
// Multiply (Most Significant Word) instructions
|
// Multiply (Most Significant Word) instructions
|
||||||
//INST(&V::arm_SMMUL, "SMMUL", "cccc01110101dddd1111mmmm00R1nnnn"), // v6
|
INST(&V::arm_SMMUL, "SMMUL", "cccc01110101dddd1111mmmm00R1nnnn"), // v6
|
||||||
//INST(&V::arm_SMMLA, "SMMLA", "cccc01110101ddddaaaammmm00R1nnnn"), // v6
|
INST(&V::arm_SMMLA, "SMMLA", "cccc01110101ddddaaaammmm00R1nnnn"), // v6
|
||||||
//INST(&V::arm_SMMLS, "SMMLS", "cccc01110101ddddaaaammmm11R1nnnn"), // v6
|
INST(&V::arm_SMMLS, "SMMLS", "cccc01110101ddddaaaammmm11R1nnnn"), // v6
|
||||||
|
|
||||||
// Multiply (Dual) instructions
|
// Multiply (Dual) instructions
|
||||||
//INST(&V::arm_SMLAD, "SMLAD", "cccc01110000ddddaaaammmm00M1nnnn"), // v6
|
INST(&V::arm_SMLAD, "SMLAD", "cccc01110000ddddaaaammmm00M1nnnn"), // v6
|
||||||
//INST(&V::arm_SMLALD, "SMLALD", "cccc01110100ddddaaaammmm00M1nnnn"), // v6
|
INST(&V::arm_SMLALD, "SMLALD", "cccc01110100ddddaaaammmm00M1nnnn"), // v6
|
||||||
//INST(&V::arm_SMLSD, "SMLSD", "cccc01110000ddddaaaammmm01M1nnnn"), // v6
|
INST(&V::arm_SMLSD, "SMLSD", "cccc01110000ddddaaaammmm01M1nnnn"), // v6
|
||||||
//INST(&V::arm_SMLSLD, "SMLSLD", "cccc01110100ddddaaaammmm01M1nnnn"), // v6
|
INST(&V::arm_SMLSLD, "SMLSLD", "cccc01110100ddddaaaammmm01M1nnnn"), // v6
|
||||||
//INST(&V::arm_SMUAD, "SMUAD", "cccc01110000dddd1111mmmm00M1nnnn"), // v6
|
INST(&V::arm_SMUAD, "SMUAD", "cccc01110000dddd1111mmmm00M1nnnn"), // v6
|
||||||
//INST(&V::arm_SMUSD, "SMUSD", "cccc01110000dddd1111mmmm01M1nnnn"), // v6
|
INST(&V::arm_SMUSD, "SMUSD", "cccc01110000dddd1111mmmm01M1nnnn"), // v6
|
||||||
|
|
||||||
// Parallel Add/Subtract (Modulo) instructions
|
// Parallel Add/Subtract (Modulo) instructions
|
||||||
//INST(&V::arm_SADD8, "SADD8", "cccc01100001nnnndddd11111001mmmm"), // v6
|
INST(&V::arm_SADD8, "SADD8", "cccc01100001nnnndddd11111001mmmm"), // v6
|
||||||
//INST(&V::arm_SADD16, "SADD16", "cccc01100001nnnndddd11110001mmmm"), // v6
|
INST(&V::arm_SADD16, "SADD16", "cccc01100001nnnndddd11110001mmmm"), // v6
|
||||||
//INST(&V::arm_SASX, "SASX", "cccc01100001nnnndddd11110011mmmm"), // v6
|
INST(&V::arm_SASX, "SASX", "cccc01100001nnnndddd11110011mmmm"), // v6
|
||||||
//INST(&V::arm_SSAX, "SSAX", "cccc01100001nnnndddd11110101mmmm"), // v6
|
INST(&V::arm_SSAX, "SSAX", "cccc01100001nnnndddd11110101mmmm"), // v6
|
||||||
//INST(&V::arm_SSUB8, "SSUB8", "cccc01100001nnnndddd11111111mmmm"), // v6
|
INST(&V::arm_SSUB8, "SSUB8", "cccc01100001nnnndddd11111111mmmm"), // v6
|
||||||
//INST(&V::arm_SSUB16, "SSUB16", "cccc01100001nnnndddd11110111mmmm"), // v6
|
INST(&V::arm_SSUB16, "SSUB16", "cccc01100001nnnndddd11110111mmmm"), // v6
|
||||||
//INST(&V::arm_UADD8, "UADD8", "cccc01100101nnnndddd11111001mmmm"), // v6
|
INST(&V::arm_UADD8, "UADD8", "cccc01100101nnnndddd11111001mmmm"), // v6
|
||||||
//INST(&V::arm_UADD16, "UADD16", "cccc01100101nnnndddd11110001mmmm"), // v6
|
INST(&V::arm_UADD16, "UADD16", "cccc01100101nnnndddd11110001mmmm"), // v6
|
||||||
//INST(&V::arm_UASX, "UASX", "cccc01100101nnnndddd11110011mmmm"), // v6
|
INST(&V::arm_UASX, "UASX", "cccc01100101nnnndddd11110011mmmm"), // v6
|
||||||
//INST(&V::arm_USAX, "USAX", "cccc01100101nnnndddd11110101mmmm"), // v6
|
INST(&V::arm_USAX, "USAX", "cccc01100101nnnndddd11110101mmmm"), // v6
|
||||||
//INST(&V::arm_USUB8, "USUB8", "cccc01100101nnnndddd11111111mmmm"), // v6
|
INST(&V::arm_USUB8, "USUB8", "cccc01100101nnnndddd11111111mmmm"), // v6
|
||||||
//INST(&V::arm_USUB16, "USUB16", "cccc01100101nnnndddd11110111mmmm"), // v6
|
INST(&V::arm_USUB16, "USUB16", "cccc01100101nnnndddd11110111mmmm"), // v6
|
||||||
|
|
||||||
// Parallel Add/Subtract (Saturating) instructions
|
// Parallel Add/Subtract (Saturating) instructions
|
||||||
//INST(&V::arm_QADD8, "QADD8", "cccc01100010nnnndddd11111001mmmm"), // v6
|
INST(&V::arm_QADD8, "QADD8", "cccc01100010nnnndddd11111001mmmm"), // v6
|
||||||
//INST(&V::arm_QADD16, "QADD16", "cccc01100010nnnndddd11110001mmmm"), // v6
|
INST(&V::arm_QADD16, "QADD16", "cccc01100010nnnndddd11110001mmmm"), // v6
|
||||||
//INST(&V::arm_QASX, "QASX", "cccc01100010nnnndddd11110011mmmm"), // v6
|
INST(&V::arm_QASX, "QASX", "cccc01100010nnnndddd11110011mmmm"), // v6
|
||||||
//INST(&V::arm_QSAX, "QSAX", "cccc01100010nnnndddd11110101mmmm"), // v6
|
INST(&V::arm_QSAX, "QSAX", "cccc01100010nnnndddd11110101mmmm"), // v6
|
||||||
//INST(&V::arm_QSUB8, "QSUB8", "cccc01100010nnnndddd11111111mmmm"), // v6
|
INST(&V::arm_QSUB8, "QSUB8", "cccc01100010nnnndddd11111111mmmm"), // v6
|
||||||
//INST(&V::arm_QSUB16, "QSUB16", "cccc01100010nnnndddd11110111mmmm"), // v6
|
INST(&V::arm_QSUB16, "QSUB16", "cccc01100010nnnndddd11110111mmmm"), // v6
|
||||||
//INST(&V::arm_UQADD8, "UQADD8", "cccc01100110nnnndddd11111001mmmm"), // v6
|
INST(&V::arm_UQADD8, "UQADD8", "cccc01100110nnnndddd11111001mmmm"), // v6
|
||||||
//INST(&V::arm_UQADD16, "UQADD16", "cccc01100110nnnndddd11110001mmmm"), // v6
|
INST(&V::arm_UQADD16, "UQADD16", "cccc01100110nnnndddd11110001mmmm"), // v6
|
||||||
//INST(&V::arm_UQASX, "UQASX", "cccc01100110nnnndddd11110011mmmm"), // v6
|
INST(&V::arm_UQASX, "UQASX", "cccc01100110nnnndddd11110011mmmm"), // v6
|
||||||
//INST(&V::arm_UQSAX, "UQSAX", "cccc01100110nnnndddd11110101mmmm"), // v6
|
INST(&V::arm_UQSAX, "UQSAX", "cccc01100110nnnndddd11110101mmmm"), // v6
|
||||||
//INST(&V::arm_UQSUB8, "UQSUB8", "cccc01100110nnnndddd11111111mmmm"), // v6
|
INST(&V::arm_UQSUB8, "UQSUB8", "cccc01100110nnnndddd11111111mmmm"), // v6
|
||||||
//INST(&V::arm_UQSUB16, "UQSUB16", "cccc01100110nnnndddd11110111mmmm"), // v6
|
INST(&V::arm_UQSUB16, "UQSUB16", "cccc01100110nnnndddd11110111mmmm"), // v6
|
||||||
|
|
||||||
// Parallel Add/Subtract (Halving) instructions
|
// Parallel Add/Subtract (Halving) instructions
|
||||||
//INST(&V::arm_SHADD8, "SHADD8", "cccc01100011nnnndddd11111001mmmm"), // v6
|
INST(&V::arm_SHADD8, "SHADD8", "cccc01100011nnnndddd11111001mmmm"), // v6
|
||||||
//INST(&V::arm_SHADD16, "SHADD16", "cccc01100011nnnndddd11110001mmmm"), // v6
|
INST(&V::arm_SHADD16, "SHADD16", "cccc01100011nnnndddd11110001mmmm"), // v6
|
||||||
//INST(&V::arm_SHASX, "SHASX", "cccc01100011nnnndddd11110011mmmm"), // v6
|
INST(&V::arm_SHASX, "SHASX", "cccc01100011nnnndddd11110011mmmm"), // v6
|
||||||
//INST(&V::arm_SHSAX, "SHSAX", "cccc01100011nnnndddd11110101mmmm"), // v6
|
INST(&V::arm_SHSAX, "SHSAX", "cccc01100011nnnndddd11110101mmmm"), // v6
|
||||||
//INST(&V::arm_SHSUB8, "SHSUB8", "cccc01100011nnnndddd11111111mmmm"), // v6
|
INST(&V::arm_SHSUB8, "SHSUB8", "cccc01100011nnnndddd11111111mmmm"), // v6
|
||||||
//INST(&V::arm_SHSUB16, "SHSUB16", "cccc01100011nnnndddd11110111mmmm"), // v6
|
INST(&V::arm_SHSUB16, "SHSUB16", "cccc01100011nnnndddd11110111mmmm"), // v6
|
||||||
//INST(&V::arm_UHADD8, "UHADD8", "cccc01100111nnnndddd11111001mmmm"), // v6
|
INST(&V::arm_UHADD8, "UHADD8", "cccc01100111nnnndddd11111001mmmm"), // v6
|
||||||
//INST(&V::arm_UHADD16, "UHADD16", "cccc01100111nnnndddd11110001mmmm"), // v6
|
INST(&V::arm_UHADD16, "UHADD16", "cccc01100111nnnndddd11110001mmmm"), // v6
|
||||||
//INST(&V::arm_UHASX, "UHASX", "cccc01100111nnnndddd11110011mmmm"), // v6
|
INST(&V::arm_UHASX, "UHASX", "cccc01100111nnnndddd11110011mmmm"), // v6
|
||||||
//INST(&V::arm_UHSAX, "UHSAX", "cccc01100111nnnndddd11110101mmmm"), // v6
|
INST(&V::arm_UHSAX, "UHSAX", "cccc01100111nnnndddd11110101mmmm"), // v6
|
||||||
//INST(&V::arm_UHSUB8, "UHSUB8", "cccc01100111nnnndddd11111111mmmm"), // v6
|
INST(&V::arm_UHSUB8, "UHSUB8", "cccc01100111nnnndddd11111111mmmm"), // v6
|
||||||
//INST(&V::arm_UHSUB16, "UHSUB16", "cccc01100111nnnndddd11110111mmmm"), // v6
|
INST(&V::arm_UHSUB16, "UHSUB16", "cccc01100111nnnndddd11110111mmmm"), // v6
|
||||||
|
|
||||||
// Saturated Add/Subtract instructions
|
// Saturated Add/Subtract instructions
|
||||||
//INST(&V::arm_QADD, "QADD", "cccc00010000nnnndddd00000101mmmm"), // v5xP
|
INST(&V::arm_QADD, "QADD", "cccc00010000nnnndddd00000101mmmm"), // v5xP
|
||||||
//INST(&V::arm_QSUB, "QSUB", "cccc00010010nnnndddd00000101mmmm"), // v5xP
|
INST(&V::arm_QSUB, "QSUB", "cccc00010010nnnndddd00000101mmmm"), // v5xP
|
||||||
//INST(&V::arm_QDADD, "QDADD", "cccc00010100nnnndddd00000101mmmm"), // v5xP
|
INST(&V::arm_QDADD, "QDADD", "cccc00010100nnnndddd00000101mmmm"), // v5xP
|
||||||
//INST(&V::arm_QDSUB, "QDSUB", "cccc00010110nnnndddd00000101mmmm"), // v5xP
|
INST(&V::arm_QDSUB, "QDSUB", "cccc00010110nnnndddd00000101mmmm"), // v5xP
|
||||||
|
|
||||||
// Status Register Access instructions
|
// Status Register Access instructions
|
||||||
//INST(&V::arm_CPS, "CPS", "111100010000---00000000---0-----"), // v6
|
INST(&V::arm_CPS, "CPS", "111100010000---00000000---0-----"), // v6
|
||||||
//INST(&V::arm_SETEND, "SETEND", "1111000100000001000000e000000000"), // v6
|
INST(&V::arm_SETEND, "SETEND", "1111000100000001000000e000000000"), // v6
|
||||||
//INST(&V::arm_MRS, "MRS", "----00010-00--------00--00000000"), // v3
|
INST(&V::arm_MRS, "MRS", "----00010-00--------00--00000000"), // v3
|
||||||
//INST(&V::arm_MSR, "MSR", "----00-10-10----1111------------"), // v3
|
INST(&V::arm_MSR, "MSR", "----00-10-10----1111------------"), // v3
|
||||||
//INST(&V::arm_RFE, "RFE", "----0001101-0000---------110----"), // v6
|
INST(&V::arm_RFE, "RFE", "----0001101-0000---------110----"), // v6
|
||||||
//INST(&V::arm_SRS, "SRS", "0000011--0-00000000000000001----"), // v6
|
INST(&V::arm_SRS, "SRS", "0000011--0-00000000000000001----"), // v6
|
||||||
|
|
||||||
#undef INST
|
#undef INST
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::stable_partition(table.begin(), table.end(), [](const auto& matcher) { return (matcher.GetMask() & 0xF0000000) != 0; });
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename V>
|
||||||
|
boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
|
const static auto table = GetArmDecodeTable<V>();
|
||||||
|
|
||||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||||
|
|
||||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
#include "common/mp.h"
|
#include "common/mp.h"
|
||||||
|
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
|
@ -79,13 +80,13 @@ private:
|
||||||
arg_index++;
|
arg_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(arg_index < N);
|
ASSERT(arg_index < N);
|
||||||
masks[arg_index] |= 1 << bit_position;
|
masks[arg_index] |= 1 << bit_position;
|
||||||
shifts[arg_index] = bit_position;
|
shifts[arg_index] = bit_position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(std::all_of(masks.begin(), masks.end(), [](auto m){ return m != 0; }));
|
ASSERT(std::all_of(masks.begin(), masks.end(), [](auto m){ return m != 0; }));
|
||||||
|
|
||||||
return std::make_tuple(masks, shifts);
|
return std::make_tuple(masks, shifts);
|
||||||
}
|
}
|
||||||
|
@ -95,20 +96,21 @@ private:
|
||||||
* the provided arg_masks and arg_shifts. The Visitor member function to call is provided as a
|
* the provided arg_masks and arg_shifts. The Visitor member function to call is provided as a
|
||||||
* template argument.
|
* template argument.
|
||||||
*/
|
*/
|
||||||
template<typename FnT, FnT fn>
|
template<typename FnT>
|
||||||
struct VisitorCaller;
|
struct VisitorCaller;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable:4800)
|
#pragma warning(disable:4800)
|
||||||
#endif
|
#endif
|
||||||
template<typename Visitor, typename ...Args, typename CallRetT, CallRetT (Visitor::*fn)(Args...)>
|
template<typename Visitor, typename ...Args, typename CallRetT>
|
||||||
struct VisitorCaller<CallRetT(Visitor::*)(Args...), fn> {
|
struct VisitorCaller<CallRetT(Visitor::*)(Args...)> {
|
||||||
template<size_t ...iota>
|
template<size_t ...iota>
|
||||||
static auto Make(std::integer_sequence<size_t, iota...>,
|
static auto Make(std::integer_sequence<size_t, iota...>,
|
||||||
|
CallRetT (Visitor::* const fn)(Args...),
|
||||||
const std::array<InstructionT, sizeof...(iota)> arg_masks,
|
const std::array<InstructionT, sizeof...(iota)> arg_masks,
|
||||||
const std::array<size_t, sizeof...(iota)> arg_shifts) {
|
const std::array<size_t, sizeof...(iota)> arg_shifts) {
|
||||||
return [arg_masks, arg_shifts](Visitor& v, InstructionT instruction) {
|
return [fn, arg_masks, arg_shifts](Visitor& v, InstructionT instruction) {
|
||||||
(void)instruction;
|
(void)instruction;
|
||||||
return (v.*fn)(static_cast<Args>((instruction & arg_masks[iota]) >> arg_shifts[iota])...);
|
return (v.*fn)(static_cast<Args>((instruction & arg_masks[iota]) >> arg_shifts[iota])...);
|
||||||
};
|
};
|
||||||
|
@ -123,15 +125,15 @@ public:
|
||||||
* Creates a matcher that can match and parse instructions based on bitstring.
|
* Creates a matcher that can match and parse instructions based on bitstring.
|
||||||
* See also: GetMaskAndExpect and GetArgInfo for format of bitstring.
|
* See also: GetMaskAndExpect and GetArgInfo for format of bitstring.
|
||||||
*/
|
*/
|
||||||
template<typename FnT, FnT fn>
|
template<typename FnT>
|
||||||
static auto GetMatcher(const char* const name, const char* const bitstring) {
|
static auto GetMatcher(FnT fn, const char* const name, const char* const bitstring) {
|
||||||
using Visitor = typename mp::MemFnInfo<FnT, fn>::class_type;
|
using Visitor = typename mp::MemFnInfo<FnT>::class_type;
|
||||||
constexpr size_t args_count = mp::MemFnInfo<FnT, fn>::args_count;
|
constexpr size_t args_count = mp::MemFnInfo<FnT>::args_count;
|
||||||
using Iota = std::make_index_sequence<args_count>;
|
using Iota = std::make_index_sequence<args_count>;
|
||||||
|
|
||||||
const auto mask_and_expect = GetMaskAndExpect(bitstring);
|
const auto mask_and_expect = GetMaskAndExpect(bitstring);
|
||||||
const auto arg_info = GetArgInfo<args_count>(bitstring);
|
const auto arg_info = GetArgInfo<args_count>(bitstring);
|
||||||
const auto proxy_fn = VisitorCaller<FnT, fn>::Make(Iota(), std::get<0>(arg_info), std::get<1>(arg_info));
|
const auto proxy_fn = VisitorCaller<FnT>::Make(Iota(), fn, std::get<0>(arg_info), std::get<1>(arg_info));
|
||||||
|
|
||||||
return MatcherT<Visitor>(name, std::get<0>(mask_and_expect), std::get<1>(mask_and_expect), proxy_fn);
|
return MatcherT<Visitor>(name, std::get<0>(mask_and_expect), std::get<1>(mask_and_expect), proxy_fn);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Arm {
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
struct Thumb16Matcher {
|
struct Thumb16Matcher {
|
||||||
using CallRetT = typename mp::MemFnInfo<decltype(&Visitor::thumb16_UDF), &Visitor::thumb16_UDF>::return_type;
|
using CallRetT = typename mp::MemFnInfo<decltype(&Visitor::thumb16_UDF)>::return_type;
|
||||||
|
|
||||||
Thumb16Matcher(const char* const name, u16 mask, u16 expect, std::function<CallRetT(Visitor&, u16)> fn)
|
Thumb16Matcher(const char* const name, u16 mask, u16 expect, std::function<CallRetT(Visitor&, u16)> fn)
|
||||||
: name(name), mask(mask), expect(expect), fn(fn) {}
|
: name(name), mask(mask), expect(expect), fn(fn) {}
|
||||||
|
@ -59,7 +59,7 @@ template<typename V>
|
||||||
boost::optional<const Thumb16Matcher<V>&> DecodeThumb16(u16 instruction) {
|
boost::optional<const Thumb16Matcher<V>&> DecodeThumb16(u16 instruction) {
|
||||||
const static std::vector<Thumb16Matcher<V>> table = {
|
const static std::vector<Thumb16Matcher<V>> table = {
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) detail::detail<Thumb16Matcher, u16, 16>::GetMatcher<decltype(fn), fn>(name, bitstring)
|
#define INST(fn, name, bitstring) detail::detail<Thumb16Matcher, u16, 16>::GetMatcher<decltype(fn)>(fn, name, bitstring)
|
||||||
|
|
||||||
// Shift (immediate), add, subtract, move and compare instructions
|
// Shift (immediate), add, subtract, move and compare instructions
|
||||||
INST(&V::thumb16_LSL_imm, "LSL (imm)", "00000vvvvvmmmddd"),
|
INST(&V::thumb16_LSL_imm, "LSL (imm)", "00000vvvvvmmmddd"),
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Arm {
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
struct Thumb32Matcher {
|
struct Thumb32Matcher {
|
||||||
using CallRetT = typename mp::MemFnInfo<decltype(&Visitor::thumb32_UDF), &Visitor::thumb32_UDF>::return_type;
|
using CallRetT = typename mp::MemFnInfo<decltype(&Visitor::thumb32_UDF)>::return_type;
|
||||||
|
|
||||||
Thumb32Matcher(const char* const name, u32 mask, u32 expect, std::function<CallRetT(Visitor&, u32)> fn)
|
Thumb32Matcher(const char* const name, u32 mask, u32 expect, std::function<CallRetT(Visitor&, u32)> fn)
|
||||||
: name(name), mask(mask), expect(expect), fn(fn) {}
|
: name(name), mask(mask), expect(expect), fn(fn) {}
|
||||||
|
@ -59,7 +59,7 @@ template<typename V>
|
||||||
boost::optional<const Thumb32Matcher<V>&> DecodeThumb32(u32 instruction) {
|
boost::optional<const Thumb32Matcher<V>&> DecodeThumb32(u32 instruction) {
|
||||||
const static std::vector<Thumb32Matcher<V>> table = {
|
const static std::vector<Thumb32Matcher<V>> table = {
|
||||||
|
|
||||||
#define INST(fn, name, bitstring) detail::detail<Thumb32Matcher, u32, 32>::GetMatcher<decltype(fn), fn>(name, bitstring)
|
#define INST(fn, name, bitstring) detail::detail<Thumb32Matcher, u32, 32>::GetMatcher<decltype(fn)>(fn, name, bitstring)
|
||||||
|
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
INST(&V::thumb32_BL_imm, "BL (imm)", "11110vvvvvvvvvvv11111vvvvvvvvvvv"), // v4T
|
INST(&V::thumb32_BL_imm, "BL (imm)", "11110vvvvvvvvvvv11111vvvvvvvvvvv"), // v4T
|
||||||
|
|
|
@ -70,6 +70,15 @@ struct ArmTranslatorVisitor final {
|
||||||
bool arm_BX(Cond cond, Reg m);
|
bool arm_BX(Cond cond, Reg m);
|
||||||
bool arm_BXJ(Cond cond, Reg m);
|
bool arm_BXJ(Cond cond, Reg m);
|
||||||
|
|
||||||
|
// Coprocessor instructions
|
||||||
|
bool arm_CDP() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_LDC() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_MCR() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_MCRR() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_MRC() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_MRRC() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_STC() { return InterpretThisInstruction(); }
|
||||||
|
|
||||||
// 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);
|
||||||
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
||||||
|
@ -139,6 +148,13 @@ struct ArmTranslatorVisitor final {
|
||||||
bool arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
bool arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
bool arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
bool arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
|
||||||
|
// Hint instructions
|
||||||
|
bool arm_PLD() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_SEV() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_WFE() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_WFI() { return InterpretThisInstruction(); }
|
||||||
|
bool arm_YIELD() { return InterpretThisInstruction(); }
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store instructions
|
||||||
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12);
|
||||||
bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
||||||
|
|
Loading…
Reference in a new issue