mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-30 02:16:06 +00:00
@@ -0,0 +1,74 @@
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2016 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*
|
||||
* Original version of table by Lioncash.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <mcl/bit/bit_count.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/frontend/decoder/decoder_detail.h"
|
||||
#include "dynarmic/frontend/decoder/matcher.h"
|
||||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
template<typename Visitor>
|
||||
using ArmMatcher = Decoder::Matcher<Visitor, u32>;
|
||||
|
||||
template<typename Visitor>
|
||||
using ArmDecodeTable = std::array<std::vector<ArmMatcher<Visitor>>, 0x1000>;
|
||||
|
||||
namespace detail {
|
||||
inline size_t ToFastLookupIndexArm(u32 instruction) {
|
||||
return ((instruction >> 4) & 0x00F) | ((instruction >> 16) & 0xFF0);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template<typename V>
|
||||
ArmDecodeTable<V> GetArmDecodeTable() {
|
||||
std::vector<ArmMatcher<V>> list = {
|
||||
|
||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(ArmMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||
#include "./arm.inc"
|
||||
#undef INST
|
||||
|
||||
};
|
||||
|
||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
||||
std::stable_sort(list.begin(), list.end(), [](const auto& matcher1, const auto& matcher2) {
|
||||
return mcl::bit::count_ones(matcher1.GetMask()) > mcl::bit::count_ones(matcher2.GetMask());
|
||||
});
|
||||
|
||||
ArmDecodeTable<V> table{};
|
||||
for (size_t i = 0; i < table.size(); ++i) {
|
||||
for (auto matcher : list) {
|
||||
const auto expect = detail::ToFastLookupIndexArm(matcher.GetExpected());
|
||||
const auto mask = detail::ToFastLookupIndexArm(matcher.GetMask());
|
||||
if ((i & mask) == expect) {
|
||||
table[i].push_back(matcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
std::optional<std::reference_wrapper<const ArmMatcher<V>>> DecodeArm(u32 instruction) {
|
||||
static const auto table = GetArmDecodeTable<V>();
|
||||
|
||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||
|
||||
const auto& subtable = table[detail::ToFastLookupIndexArm(instruction)];
|
||||
auto iter = std::find_if(subtable.begin(), subtable.end(), matches_instruction);
|
||||
return iter != subtable.end() ? std::optional<std::reference_wrapper<const ArmMatcher<V>>>(*iter) : std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
@@ -0,0 +1,316 @@
|
||||
// Barrier instructions
|
||||
INST(arm_DMB, "DMB", "1111010101111111111100000101oooo") // v7
|
||||
INST(arm_DSB, "DSB", "1111010101111111111100000100oooo") // v7
|
||||
INST(arm_ISB, "ISB", "1111010101111111111100000110oooo") // v7
|
||||
|
||||
// Branch instructions
|
||||
INST(arm_BLX_imm, "BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv") // v5
|
||||
INST(arm_BLX_reg, "BLX (reg)", "cccc000100101111111111110011mmmm") // v5
|
||||
INST(arm_B, "B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv") // v1
|
||||
INST(arm_BL, "BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv") // v1
|
||||
INST(arm_BX, "BX", "cccc000100101111111111110001mmmm") // v4T
|
||||
INST(arm_BXJ, "BXJ", "cccc000100101111111111110010mmmm") // v5J
|
||||
|
||||
// CRC32 instructions
|
||||
INST(arm_CRC32, "CRC32", "cccc00010zz0nnnndddd00000100mmmm") // v8
|
||||
INST(arm_CRC32C, "CRC32C", "cccc00010zz0nnnndddd00100100mmmm") // v8
|
||||
|
||||
// Coprocessor instructions
|
||||
INST(arm_CDP, "CDP", "cccc1110ooooNNNNDDDDppppooo0MMMM") // v2 (CDP2: v5)
|
||||
INST(arm_LDC, "LDC", "cccc110pudw1nnnnDDDDppppvvvvvvvv") // v2 (LDC2: v5)
|
||||
INST(arm_MCR, "MCR", "cccc1110ooo0NNNNttttppppooo1MMMM") // v2 (MCR2: v5)
|
||||
INST(arm_MCRR, "MCRR", "cccc11000100uuuuttttppppooooMMMM") // v5E (MCRR2: v6)
|
||||
INST(arm_MRC, "MRC", "cccc1110ooo1NNNNttttppppooo1MMMM") // v2 (MRC2: v5)
|
||||
INST(arm_MRRC, "MRRC", "cccc11000101uuuuttttppppooooMMMM") // v5E (MRRC2: v6)
|
||||
INST(arm_STC, "STC", "cccc110pudw0nnnnDDDDppppvvvvvvvv") // v2 (STC2: v5)
|
||||
|
||||
// Data Processing instructions
|
||||
INST(arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_ADD_reg, "ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_ADD_rsr, "ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_AND_imm, "AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_AND_reg, "AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_AND_rsr, "AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_BIC_imm, "BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_BIC_reg, "BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_BIC_rsr, "BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_CMN_imm, "CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv") // v1
|
||||
INST(arm_CMN_reg, "CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm") // v1
|
||||
INST(arm_CMN_rsr, "CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm") // v1
|
||||
INST(arm_CMP_imm, "CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv") // v1
|
||||
INST(arm_CMP_reg, "CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm") // v1
|
||||
INST(arm_CMP_rsr, "CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm") // v1
|
||||
INST(arm_EOR_imm, "EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_EOR_reg, "EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_EOR_rsr, "EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_MOV_imm, "MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_MOV_reg, "MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_MOV_rsr, "MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm") // v1
|
||||
INST(arm_MVN_imm, "MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_MVN_reg, "MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_MVN_rsr, "MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm") // v1
|
||||
INST(arm_ORR_imm, "ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_ORR_reg, "ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_ORR_rsr, "ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_RSB_imm, "RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_RSB_reg, "RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_RSB_rsr, "RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_RSC_imm, "RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_RSC_reg, "RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_RSC_rsr, "RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_SBC_imm, "SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_SBC_reg, "SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_SBC_rsr, "SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_SUB_imm, "SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv") // v1
|
||||
INST(arm_SUB_reg, "SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm") // v1
|
||||
INST(arm_SUB_rsr, "SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm") // v1
|
||||
INST(arm_TEQ_imm, "TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv") // v1
|
||||
INST(arm_TEQ_reg, "TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm") // v1
|
||||
INST(arm_TEQ_rsr, "TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm") // v1
|
||||
INST(arm_TST_imm, "TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv") // v1
|
||||
INST(arm_TST_reg, "TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm") // v1
|
||||
INST(arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm") // v1
|
||||
|
||||
// Exception Generating instructions
|
||||
INST(arm_BKPT, "BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv") // v5
|
||||
INST(arm_SVC, "SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv") // v1
|
||||
INST(arm_UDF, "UDF", "111001111111------------1111----")
|
||||
|
||||
// Extension instructions
|
||||
INST(arm_SXTB, "SXTB", "cccc011010101111ddddrr000111mmmm") // v6
|
||||
INST(arm_SXTB16, "SXTB16", "cccc011010001111ddddrr000111mmmm") // v6
|
||||
INST(arm_SXTH, "SXTH", "cccc011010111111ddddrr000111mmmm") // v6
|
||||
INST(arm_SXTAB, "SXTAB", "cccc01101010nnnnddddrr000111mmmm") // v6
|
||||
INST(arm_SXTAB16, "SXTAB16", "cccc01101000nnnnddddrr000111mmmm") // v6
|
||||
INST(arm_SXTAH, "SXTAH", "cccc01101011nnnnddddrr000111mmmm") // v6
|
||||
INST(arm_UXTB, "UXTB", "cccc011011101111ddddrr000111mmmm") // v6
|
||||
INST(arm_UXTB16, "UXTB16", "cccc011011001111ddddrr000111mmmm") // v6
|
||||
INST(arm_UXTH, "UXTH", "cccc011011111111ddddrr000111mmmm") // v6
|
||||
INST(arm_UXTAB, "UXTAB", "cccc01101110nnnnddddrr000111mmmm") // v6
|
||||
INST(arm_UXTAB16, "UXTAB16", "cccc01101100nnnnddddrr000111mmmm") // v6
|
||||
INST(arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm") // v6
|
||||
|
||||
// Hint instructions
|
||||
INST(arm_PLD_imm, "PLD (imm)", "11110101uz01nnnn1111iiiiiiiiiiii") // v5E for PLD; v7 for PLDW
|
||||
INST(arm_PLD_reg, "PLD (reg)", "11110111uz01nnnn1111iiiiitt0mmmm") // v5E for PLD; v7 for PLDW
|
||||
INST(arm_SEV, "SEV", "----0011001000001111000000000100") // v6K
|
||||
INST(arm_SEVL, "SEVL", "----0011001000001111000000000101") // v8
|
||||
INST(arm_WFE, "WFE", "----0011001000001111000000000010") // v6K
|
||||
INST(arm_WFI, "WFI", "----0011001000001111000000000011") // v6K
|
||||
INST(arm_YIELD, "YIELD", "----0011001000001111000000000001") // v6K
|
||||
INST(arm_NOP, "Reserved Hint", "----0011001000001111------------")
|
||||
INST(arm_NOP, "Reserved Hint", "----001100100000111100000000----")
|
||||
|
||||
// Synchronization Primitive instructions
|
||||
INST(arm_CLREX, "CLREX", "11110101011111111111000000011111") // v6K
|
||||
INST(arm_SWP, "SWP", "cccc00010000nnnntttt00001001uuuu") // v2S (v6: Deprecated)
|
||||
INST(arm_SWPB, "SWPB", "cccc00010100nnnntttt00001001uuuu") // v2S (v6: Deprecated)
|
||||
INST(arm_STL, "STL", "cccc00011000nnnn111111001001tttt") // v8
|
||||
INST(arm_STLEX, "STLEX", "cccc00011000nnnndddd11101001tttt") // v8
|
||||
INST(arm_STREX, "STREX", "cccc00011000nnnndddd11111001mmmm") // v6
|
||||
INST(arm_LDA, "LDA", "cccc00011001nnnndddd110010011111") // v8
|
||||
INST(arm_LDAEX, "LDAEX", "cccc00011001nnnndddd111010011111") // v8
|
||||
INST(arm_LDREX, "LDREX", "cccc00011001nnnndddd111110011111") // v6
|
||||
INST(arm_STLEXD, "STLEXD", "cccc00011010nnnndddd11101001mmmm") // v8
|
||||
INST(arm_STREXD, "STREXD", "cccc00011010nnnndddd11111001mmmm") // v6K
|
||||
INST(arm_LDAEXD, "LDAEXD", "cccc00011011nnnndddd111010011111") // v8
|
||||
INST(arm_LDREXD, "LDREXD", "cccc00011011nnnndddd111110011111") // v6K
|
||||
INST(arm_STLB, "STLB", "cccc00011100nnnn111111001001tttt") // v8
|
||||
INST(arm_STLEXB, "STLEXB", "cccc00011100nnnndddd11101001mmmm") // v8
|
||||
INST(arm_STREXB, "STREXB", "cccc00011100nnnndddd11111001mmmm") // v6K
|
||||
INST(arm_LDAB, "LDAB", "cccc00011101nnnndddd110010011111") // v8
|
||||
INST(arm_LDAEXB, "LDAEXB", "cccc00011101nnnndddd111010011111") // v8
|
||||
INST(arm_LDREXB, "LDREXB", "cccc00011101nnnndddd111110011111") // v6K
|
||||
INST(arm_STLH, "STLH", "cccc00011110nnnn111111001001mmmm") // v8
|
||||
INST(arm_STLEXH, "STLEXH", "cccc00011110nnnndddd11101001mmmm") // v8
|
||||
INST(arm_STREXH, "STREXH", "cccc00011110nnnndddd11111001mmmm") // v6K
|
||||
INST(arm_LDAH, "LDAH", "cccc00011111nnnndddd110010011111") // v8
|
||||
INST(arm_LDAEXH, "LDAEXH", "cccc00011111nnnndddd111010011111") // v8
|
||||
INST(arm_LDREXH, "LDREXH", "cccc00011111nnnndddd111110011111") // v6K
|
||||
|
||||
// Load/Store instructions
|
||||
INST(arm_LDRBT, "LDRBT (A1)", "----0100-111--------------------") // v1
|
||||
INST(arm_LDRBT, "LDRBT (A2)", "----0110-111---------------0----") // v1
|
||||
INST(arm_LDRHT, "LDRHT (A1)", "----0000-111------------1011----") // v6T2
|
||||
INST(arm_LDRHT, "LDRHT (A1)", "----0000-1111111--------1011----") // v6T2
|
||||
INST(arm_LDRHT, "LDRHT (A2)", "----0000-011--------00001011----") // v6T2
|
||||
INST(arm_LDRSBT, "LDRSBT (A1)", "----0000-111------------1101----") // v6T2
|
||||
INST(arm_LDRSBT, "LDRSBT (A2)", "----0000-011--------00001101----") // v6T2
|
||||
INST(arm_LDRSHT, "LDRSHT (A1)", "----0000-111------------1111----") // v6T2
|
||||
INST(arm_LDRSHT, "LDRSHT (A2)", "----0000-011--------00001111----") // v6T2
|
||||
INST(arm_LDRT, "LDRT (A1)", "----0100-011--------------------") // v1
|
||||
INST(arm_LDRT, "LDRT (A2)", "----0110-011---------------0----") // v1
|
||||
INST(arm_STRBT, "STRBT (A1)", "----0100-110--------------------") // v1
|
||||
INST(arm_STRBT, "STRBT (A2)", "----0110-110---------------0----") // v1
|
||||
INST(arm_STRHT, "STRHT (A1)", "----0000-110------------1011----") // v6T2
|
||||
INST(arm_STRHT, "STRHT (A2)", "----0000-010--------00001011----") // v6T2
|
||||
INST(arm_STRT, "STRT (A1)", "----0100-010--------------------") // v1
|
||||
INST(arm_STRT, "STRT (A2)", "----0110-010---------------0----") // v1
|
||||
INST(arm_LDR_lit, "LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv") // v1
|
||||
INST(arm_LDR_imm, "LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv") // v1
|
||||
INST(arm_LDR_reg, "LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm") // v1
|
||||
INST(arm_LDRB_lit, "LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv") // v1
|
||||
INST(arm_LDRB_imm, "LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv") // v1
|
||||
INST(arm_LDRB_reg, "LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm") // v1
|
||||
INST(arm_LDRD_lit, "LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv") // v5E
|
||||
INST(arm_LDRD_imm, "LDRD (imm)", "cccc000pu1w0nnnnttttvvvv1101vvvv") // v5E
|
||||
INST(arm_LDRD_reg, "LDRD (reg)", "cccc000pu0w0nnnntttt00001101mmmm") // v5E
|
||||
INST(arm_LDRH_lit, "LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv") // v4
|
||||
INST(arm_LDRH_imm, "LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv") // v4
|
||||
INST(arm_LDRH_reg, "LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm") // v4
|
||||
INST(arm_LDRSB_lit, "LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv") // v4
|
||||
INST(arm_LDRSB_imm, "LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv") // v4
|
||||
INST(arm_LDRSB_reg, "LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm") // v4
|
||||
INST(arm_LDRSH_lit, "LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv") // v4
|
||||
INST(arm_LDRSH_imm, "LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv") // v4
|
||||
INST(arm_LDRSH_reg, "LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm") // v4
|
||||
INST(arm_STR_imm, "STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv") // v1
|
||||
INST(arm_STR_reg, "STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm") // v1
|
||||
INST(arm_STRB_imm, "STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv") // v1
|
||||
INST(arm_STRB_reg, "STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm") // v1
|
||||
INST(arm_STRD_imm, "STRD (imm)", "cccc000pu1w0nnnnttttvvvv1111vvvv") // v5E
|
||||
INST(arm_STRD_reg, "STRD (reg)", "cccc000pu0w0nnnntttt00001111mmmm") // v5E
|
||||
INST(arm_STRH_imm, "STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv") // v4
|
||||
INST(arm_STRH_reg, "STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm") // v4
|
||||
|
||||
// Load/Store Multiple instructions
|
||||
INST(arm_LDM, "LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx") // v1
|
||||
INST(arm_LDMDA, "LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx") // v1
|
||||
INST(arm_LDMDB, "LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx") // v1
|
||||
INST(arm_LDMIB, "LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx") // v1
|
||||
INST(arm_LDM_usr, "LDM (usr reg)", "----100--101--------------------") // v1
|
||||
INST(arm_LDM_eret, "LDM (exce ret)", "----100--1-1----1---------------") // v1
|
||||
INST(arm_STM, "STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx") // v1
|
||||
INST(arm_STMDA, "STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx") // v1
|
||||
INST(arm_STMDB, "STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx") // v1
|
||||
INST(arm_STMIB, "STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx") // v1
|
||||
INST(arm_STM_usr, "STM (usr reg)", "----100--100--------------------") // v1
|
||||
|
||||
// Miscellaneous instructions
|
||||
INST(arm_BFC, "BFC", "cccc0111110vvvvvddddvvvvv0011111") // v6T2
|
||||
INST(arm_BFI, "BFI", "cccc0111110vvvvvddddvvvvv001nnnn") // v6T2
|
||||
INST(arm_CLZ, "CLZ", "cccc000101101111dddd11110001mmmm") // v5
|
||||
INST(arm_MOVT, "MOVT", "cccc00110100vvvvddddvvvvvvvvvvvv") // v6T2
|
||||
INST(arm_MOVW, "MOVW", "cccc00110000vvvvddddvvvvvvvvvvvv") // v6T2
|
||||
INST(arm_NOP, "NOP", "----0011001000001111000000000000") // v6K
|
||||
INST(arm_SBFX, "SBFX", "cccc0111101wwwwwddddvvvvv101nnnn") // v6T2
|
||||
INST(arm_SEL, "SEL", "cccc01101000nnnndddd11111011mmmm") // v6
|
||||
INST(arm_UBFX, "UBFX", "cccc0111111wwwwwddddvvvvv101nnnn") // v6T2
|
||||
|
||||
// Unsigned Sum of Absolute Differences instructions
|
||||
INST(arm_USAD8, "USAD8", "cccc01111000dddd1111mmmm0001nnnn") // v6
|
||||
INST(arm_USADA8, "USADA8", "cccc01111000ddddaaaammmm0001nnnn") // v6
|
||||
|
||||
// Packing instructions
|
||||
INST(arm_PKHBT, "PKHBT", "cccc01101000nnnnddddvvvvv001mmmm") // v6K
|
||||
INST(arm_PKHTB, "PKHTB", "cccc01101000nnnnddddvvvvv101mmmm") // v6K
|
||||
|
||||
// Reversal instructions
|
||||
INST(arm_RBIT, "RBIT", "cccc011011111111dddd11110011mmmm") // v6T2
|
||||
INST(arm_REV, "REV", "cccc011010111111dddd11110011mmmm") // v6
|
||||
INST(arm_REV16, "REV16", "cccc011010111111dddd11111011mmmm") // v6
|
||||
INST(arm_REVSH, "REVSH", "cccc011011111111dddd11111011mmmm") // v6
|
||||
|
||||
// Saturation instructions
|
||||
INST(arm_SSAT, "SSAT", "cccc0110101vvvvvddddvvvvvr01nnnn") // v6
|
||||
INST(arm_SSAT16, "SSAT16", "cccc01101010vvvvdddd11110011nnnn") // v6
|
||||
INST(arm_USAT, "USAT", "cccc0110111vvvvvddddvvvvvr01nnnn") // v6
|
||||
INST(arm_USAT16, "USAT16", "cccc01101110vvvvdddd11110011nnnn") // v6
|
||||
|
||||
// Divide instructions
|
||||
INST(arm_SDIV, "SDIV", "cccc01110001dddd1111mmmm0001nnnn") // v7a
|
||||
INST(arm_UDIV, "UDIV", "cccc01110011dddd1111mmmm0001nnnn") // v7a
|
||||
|
||||
// Multiply (Normal) instructions
|
||||
INST(arm_MLA, "MLA", "cccc0000001Sddddaaaammmm1001nnnn") // v2
|
||||
INST(arm_MLS, "MLS", "cccc00000110ddddaaaammmm1001nnnn") // v6T2
|
||||
INST(arm_MUL, "MUL", "cccc0000000Sdddd0000mmmm1001nnnn") // v2
|
||||
|
||||
// Multiply (Long) instructions
|
||||
INST(arm_SMLAL, "SMLAL", "cccc0000111Sddddaaaammmm1001nnnn") // v3M
|
||||
INST(arm_SMULL, "SMULL", "cccc0000110Sddddaaaammmm1001nnnn") // v3M
|
||||
INST(arm_UMAAL, "UMAAL", "cccc00000100ddddaaaammmm1001nnnn") // v6
|
||||
INST(arm_UMLAL, "UMLAL", "cccc0000101Sddddaaaammmm1001nnnn") // v3M
|
||||
INST(arm_UMULL, "UMULL", "cccc0000100Sddddaaaammmm1001nnnn") // v3M
|
||||
|
||||
// Multiply (Halfword) instructions
|
||||
INST(arm_SMLALxy, "SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn") // v5xP
|
||||
INST(arm_SMLAxy, "SMLAXY", "cccc00010000ddddaaaammmm1xy0nnnn") // v5xP
|
||||
INST(arm_SMULxy, "SMULXY", "cccc00010110dddd0000mmmm1xy0nnnn") // v5xP
|
||||
|
||||
// Multiply (Word by Halfword) instructions
|
||||
INST(arm_SMLAWy, "SMLAWY", "cccc00010010ddddaaaammmm1y00nnnn") // v5xP
|
||||
INST(arm_SMULWy, "SMULWY", "cccc00010010dddd0000mmmm1y10nnnn") // v5xP
|
||||
|
||||
// Multiply (Most Significant Word) instructions
|
||||
INST(arm_SMMUL, "SMMUL", "cccc01110101dddd1111mmmm00R1nnnn") // v6
|
||||
INST(arm_SMMLA, "SMMLA", "cccc01110101ddddaaaammmm00R1nnnn") // v6
|
||||
INST(arm_SMMLS, "SMMLS", "cccc01110101ddddaaaammmm11R1nnnn") // v6
|
||||
|
||||
// Multiply (Dual) instructions
|
||||
INST(arm_SMLAD, "SMLAD", "cccc01110000ddddaaaammmm00M1nnnn") // v6
|
||||
INST(arm_SMLALD, "SMLALD", "cccc01110100ddddaaaammmm00M1nnnn") // v6
|
||||
INST(arm_SMLSD, "SMLSD", "cccc01110000ddddaaaammmm01M1nnnn") // v6
|
||||
INST(arm_SMLSLD, "SMLSLD", "cccc01110100ddddaaaammmm01M1nnnn") // v6
|
||||
INST(arm_SMUAD, "SMUAD", "cccc01110000dddd1111mmmm00M1nnnn") // v6
|
||||
INST(arm_SMUSD, "SMUSD", "cccc01110000dddd1111mmmm01M1nnnn") // v6
|
||||
|
||||
// Parallel Add/Subtract (Modulo) instructions
|
||||
INST(arm_SADD8, "SADD8", "cccc01100001nnnndddd11111001mmmm") // v6
|
||||
INST(arm_SADD16, "SADD16", "cccc01100001nnnndddd11110001mmmm") // v6
|
||||
INST(arm_SASX, "SASX", "cccc01100001nnnndddd11110011mmmm") // v6
|
||||
INST(arm_SSAX, "SSAX", "cccc01100001nnnndddd11110101mmmm") // v6
|
||||
INST(arm_SSUB8, "SSUB8", "cccc01100001nnnndddd11111111mmmm") // v6
|
||||
INST(arm_SSUB16, "SSUB16", "cccc01100001nnnndddd11110111mmmm") // v6
|
||||
INST(arm_UADD8, "UADD8", "cccc01100101nnnndddd11111001mmmm") // v6
|
||||
INST(arm_UADD16, "UADD16", "cccc01100101nnnndddd11110001mmmm") // v6
|
||||
INST(arm_UASX, "UASX", "cccc01100101nnnndddd11110011mmmm") // v6
|
||||
INST(arm_USAX, "USAX", "cccc01100101nnnndddd11110101mmmm") // v6
|
||||
INST(arm_USUB8, "USUB8", "cccc01100101nnnndddd11111111mmmm") // v6
|
||||
INST(arm_USUB16, "USUB16", "cccc01100101nnnndddd11110111mmmm") // v6
|
||||
|
||||
// Parallel Add/Subtract (Saturating) instructions
|
||||
INST(arm_QADD8, "QADD8", "cccc01100010nnnndddd11111001mmmm") // v6
|
||||
INST(arm_QADD16, "QADD16", "cccc01100010nnnndddd11110001mmmm") // v6
|
||||
INST(arm_QASX, "QASX", "cccc01100010nnnndddd11110011mmmm") // v6
|
||||
INST(arm_QSAX, "QSAX", "cccc01100010nnnndddd11110101mmmm") // v6
|
||||
INST(arm_QSUB8, "QSUB8", "cccc01100010nnnndddd11111111mmmm") // v6
|
||||
INST(arm_QSUB16, "QSUB16", "cccc01100010nnnndddd11110111mmmm") // v6
|
||||
INST(arm_UQADD8, "UQADD8", "cccc01100110nnnndddd11111001mmmm") // v6
|
||||
INST(arm_UQADD16, "UQADD16", "cccc01100110nnnndddd11110001mmmm") // v6
|
||||
INST(arm_UQASX, "UQASX", "cccc01100110nnnndddd11110011mmmm") // v6
|
||||
INST(arm_UQSAX, "UQSAX", "cccc01100110nnnndddd11110101mmmm") // v6
|
||||
INST(arm_UQSUB8, "UQSUB8", "cccc01100110nnnndddd11111111mmmm") // v6
|
||||
INST(arm_UQSUB16, "UQSUB16", "cccc01100110nnnndddd11110111mmmm") // v6
|
||||
|
||||
// Parallel Add/Subtract (Halving) instructions
|
||||
INST(arm_SHADD8, "SHADD8", "cccc01100011nnnndddd11111001mmmm") // v6
|
||||
INST(arm_SHADD16, "SHADD16", "cccc01100011nnnndddd11110001mmmm") // v6
|
||||
INST(arm_SHASX, "SHASX", "cccc01100011nnnndddd11110011mmmm") // v6
|
||||
INST(arm_SHSAX, "SHSAX", "cccc01100011nnnndddd11110101mmmm") // v6
|
||||
INST(arm_SHSUB8, "SHSUB8", "cccc01100011nnnndddd11111111mmmm") // v6
|
||||
INST(arm_SHSUB16, "SHSUB16", "cccc01100011nnnndddd11110111mmmm") // v6
|
||||
INST(arm_UHADD8, "UHADD8", "cccc01100111nnnndddd11111001mmmm") // v6
|
||||
INST(arm_UHADD16, "UHADD16", "cccc01100111nnnndddd11110001mmmm") // v6
|
||||
INST(arm_UHASX, "UHASX", "cccc01100111nnnndddd11110011mmmm") // v6
|
||||
INST(arm_UHSAX, "UHSAX", "cccc01100111nnnndddd11110101mmmm") // v6
|
||||
INST(arm_UHSUB8, "UHSUB8", "cccc01100111nnnndddd11111111mmmm") // v6
|
||||
INST(arm_UHSUB16, "UHSUB16", "cccc01100111nnnndddd11110111mmmm") // v6
|
||||
|
||||
// Saturated Add/Subtract instructions
|
||||
INST(arm_QADD, "QADD", "cccc00010000nnnndddd00000101mmmm") // v5xP
|
||||
INST(arm_QSUB, "QSUB", "cccc00010010nnnndddd00000101mmmm") // v5xP
|
||||
INST(arm_QDADD, "QDADD", "cccc00010100nnnndddd00000101mmmm") // v5xP
|
||||
INST(arm_QDSUB, "QDSUB", "cccc00010110nnnndddd00000101mmmm") // v5xP
|
||||
|
||||
// Status Register Access instructions
|
||||
INST(arm_CPS, "CPS", "111100010000---00000000---0-----") // v6
|
||||
INST(arm_SETEND, "SETEND", "1111000100000001000000e000000000") // v6
|
||||
INST(arm_MRS, "MRS", "cccc000100001111dddd000000000000") // v3
|
||||
INST(arm_MSR_imm, "MSR (imm)", "cccc00110010mmmm1111rrrrvvvvvvvv") // v3
|
||||
INST(arm_MSR_reg, "MSR (reg)", "cccc00010010mmmm111100000000nnnn") // v3
|
||||
INST(arm_RFE, "RFE", "1111100--0-1----0000101000000000") // v6
|
||||
INST(arm_SRS, "SRS", "1111100--1-0110100000101000-----") // v6
|
||||
@@ -0,0 +1,78 @@
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2020 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <mcl/bit/bit_count.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/frontend/decoder/decoder_detail.h"
|
||||
#include "dynarmic/frontend/decoder/matcher.h"
|
||||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
template<typename Visitor>
|
||||
using ASIMDMatcher = Decoder::Matcher<Visitor, u32>;
|
||||
|
||||
template<typename V>
|
||||
std::vector<ASIMDMatcher<V>> GetASIMDDecodeTable() {
|
||||
std::vector<ASIMDMatcher<V>> table = {
|
||||
|
||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(ASIMDMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||
#include "./asimd.inc"
|
||||
#undef INST
|
||||
|
||||
};
|
||||
|
||||
// Exceptions to the rule of thumb.
|
||||
const std::set<std::string> comes_first{
|
||||
"VBIC, VMOV, VMVN, VORR (immediate)",
|
||||
"VEXT",
|
||||
"VTBL",
|
||||
"VTBX",
|
||||
"VDUP (scalar)",
|
||||
};
|
||||
const std::set<std::string> comes_last{
|
||||
"VMLA (scalar)",
|
||||
"VMLAL (scalar)",
|
||||
"VQDMLAL/VQDMLSL (scalar)",
|
||||
"VMUL (scalar)",
|
||||
"VMULL (scalar)",
|
||||
"VQDMULL (scalar)",
|
||||
"VQDMULH (scalar)",
|
||||
"VQRDMULH (scalar)",
|
||||
};
|
||||
const auto sort_begin = std::stable_partition(table.begin(), table.end(), [&](const auto& matcher) {
|
||||
return comes_first.count(matcher.GetName()) > 0;
|
||||
});
|
||||
const auto sort_end = std::stable_partition(table.begin(), table.end(), [&](const auto& matcher) {
|
||||
return comes_last.count(matcher.GetName()) == 0;
|
||||
});
|
||||
|
||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
||||
std::stable_sort(sort_begin, sort_end, [](const auto& matcher1, const auto& matcher2) {
|
||||
return mcl::bit::count_ones(matcher1.GetMask()) > mcl::bit::count_ones(matcher2.GetMask());
|
||||
});
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
std::optional<std::reference_wrapper<const ASIMDMatcher<V>>> DecodeASIMD(u32 instruction) {
|
||||
static const auto table = GetASIMDDecodeTable<V>();
|
||||
|
||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||
|
||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||
return iter != table.end() ? std::optional<std::reference_wrapper<const ASIMDMatcher<V>>>(*iter) : std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
@@ -0,0 +1,172 @@
|
||||
// Three registers of the same length
|
||||
INST(asimd_VHADD, "VHADD", "1111001U0Dzznnnndddd0000NQM0mmmm") // ASIMD
|
||||
INST(asimd_VQADD, "VQADD", "1111001U0Dzznnnndddd0000NQM1mmmm") // ASIMD
|
||||
INST(asimd_VRHADD, "VRHADD", "1111001U0Dzznnnndddd0001NQM0mmmm") // ASIMD
|
||||
INST(asimd_VAND_reg, "VAND (register)", "111100100D00nnnndddd0001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VBIC_reg, "VBIC (register)", "111100100D01nnnndddd0001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VORR_reg, "VORR (register)", "111100100D10nnnndddd0001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VORN_reg, "VORN (register)", "111100100D11nnnndddd0001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VEOR_reg, "VEOR (register)", "111100110D00nnnndddd0001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VBSL, "VBSL", "111100110D01nnnndddd0001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VBIT, "VBIT", "111100110D10nnnndddd0001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VBIF, "VBIF", "111100110D11nnnndddd0001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VHSUB, "VHSUB", "1111001U0Dzznnnndddd0010NQM0mmmm") // ASIMD
|
||||
INST(asimd_VQSUB, "VQSUB", "1111001U0Dzznnnndddd0010NQM1mmmm") // ASIMD
|
||||
INST(asimd_VCGT_reg, "VCGT (register)", "1111001U0Dzznnnndddd0011NQM0mmmm") // ASIMD
|
||||
INST(asimd_VCGE_reg, "VCGE (register)", "1111001U0Dzznnnndddd0011NQM1mmmm") // ASIMD
|
||||
INST(asimd_VSHL_reg, "VSHL (register)", "1111001U0Dzznnnndddd0100NQM0mmmm") // ASIMD
|
||||
INST(asimd_VQSHL_reg, "VQSHL (register)", "1111001U0Dzznnnndddd0100NQM1mmmm") // ASIMD
|
||||
INST(asimd_VRSHL, "VRSHL", "1111001U0Dzznnnndddd0101NQM0mmmm") // ASIMD
|
||||
//INST(asimd_VQRSHL, "VQRSHL", "1111001U0-CC--------0101---1----") // ASIMD
|
||||
INST(asimd_VMAX, "VMAX/VMIN (integer)", "1111001U0Dzznnnnmmmm0110NQMommmm") // ASIMD
|
||||
INST(asimd_VABD, "VABD", "1111001U0Dzznnnndddd0111NQM0mmmm") // ASIMD
|
||||
INST(asimd_VABA, "VABA", "1111001U0Dzznnnndddd0111NQM1mmmm") // ASIMD
|
||||
INST(asimd_VADD_int, "VADD (integer)", "111100100Dzznnnndddd1000NQM0mmmm") // ASIMD
|
||||
INST(asimd_VSUB_int, "VSUB (integer)", "111100110Dzznnnndddd1000NQM0mmmm") // ASIMD
|
||||
INST(asimd_VTST, "VTST", "111100100Dzznnnndddd1000NQM1mmmm") // ASIMD
|
||||
INST(asimd_VCEQ_reg, "VCEG (register)", "111100110Dzznnnndddd1000NQM1mmmm") // ASIMD
|
||||
INST(asimd_VMLA, "VMLA/VMLS", "1111001o0Dzznnnndddd1001NQM0mmmm") // ASIMD
|
||||
INST(asimd_VMUL, "VMUL", "1111001P0Dzznnnndddd1001NQM1mmmm") // ASIMD
|
||||
INST(asimd_VPMAX_int, "VPMAX/VPMIN (integer)", "1111001U0Dzznnnndddd1010NQMommmm") // ASIMD
|
||||
INST(v8_VMAXNM, "VMAXNM", "111100110D0znnnndddd1111NQM1mmmm") // v8
|
||||
INST(v8_VMINNM, "VMINNM", "111100110D1znnnndddd1111NQM1mmmm") // v8
|
||||
INST(asimd_VQDMULH, "VQDMULH", "111100100Dzznnnndddd1011NQM0mmmm") // ASIMD
|
||||
INST(asimd_VQRDMULH, "VQRDMULH", "111100110Dzznnnndddd1011NQM0mmmm") // ASIMD
|
||||
INST(asimd_VPADD, "VPADD", "111100100Dzznnnndddd1011NQM1mmmm") // ASIMD
|
||||
INST(asimd_VFMA, "VFMA", "111100100D0znnnndddd1100NQM1mmmm") // ASIMD
|
||||
INST(asimd_VFMS, "VFMS", "111100100D1znnnndddd1100NQM1mmmm") // ASIMD
|
||||
INST(asimd_VADD_float, "VADD (floating-point)", "111100100D0znnnndddd1101NQM0mmmm") // ASIMD
|
||||
INST(asimd_VSUB_float, "VSUB (floating-point)", "111100100D1znnnndddd1101NQM0mmmm") // ASIMD
|
||||
INST(asimd_VPADD_float, "VPADD (floating-point)", "111100110D0znnnndddd1101NQM0mmmm") // ASIMD
|
||||
INST(asimd_VABD_float, "VABD (floating-point)", "111100110D1znnnndddd1101NQM0mmmm") // ASIMD
|
||||
INST(asimd_VMLA_float, "VMLA (floating-point)", "111100100D0znnnndddd1101NQM1mmmm") // ASIMD
|
||||
INST(asimd_VMLS_float, "VMLS (floating-point)", "111100100D1znnnndddd1101NQM1mmmm") // ASIMD
|
||||
INST(asimd_VMUL_float, "VMUL (floating-point)", "111100110D0znnnndddd1101NQM1mmmm") // ASIMD
|
||||
INST(asimd_VCEQ_reg_float, "VCEQ (register)", "111100100D0znnnndddd1110NQM0mmmm") // ASIMD
|
||||
INST(asimd_VCGE_reg_float, "VCGE (register)", "111100110D0znnnndddd1110NQM0mmmm") // ASIMD
|
||||
INST(asimd_VCGT_reg_float, "VCGT (register)", "111100110D1znnnndddd1110NQM0mmmm") // ASIMD
|
||||
INST(asimd_VACGE, "VACGE", "111100110Doznnnndddd1110NQM1mmmm") // ASIMD
|
||||
INST(asimd_VMAX_float, "VMAX (floating-point)", "111100100D0znnnndddd1111NQM0mmmm") // ASIMD
|
||||
INST(asimd_VMIN_float, "VMIN (floating-point)", "111100100D1znnnndddd1111NQM0mmmm") // ASIMD
|
||||
INST(asimd_VPMAX_float, "VPMAX (floating-point)", "111100110D0znnnndddd1111NQM0mmmm") // ASIMD
|
||||
INST(asimd_VPMIN_float, "VPMIN (floating-point)", "111100110D1znnnndddd1111NQM0mmmm") // ASIMD
|
||||
INST(asimd_VRECPS, "VRECPS", "111100100D0znnnndddd1111NQM1mmmm") // ASIMD
|
||||
INST(asimd_VRSQRTS, "VRSQRTS", "111100100D1znnnndddd1111NQM1mmmm") // ASIMD
|
||||
INST(v8_SHA256H, "SHA256H", "111100110D00nnnndddd1100NQM0mmmm") // v8
|
||||
INST(v8_SHA256H2, "SHA256H2", "111100110D01nnnndddd1100NQM0mmmm") // v8
|
||||
INST(v8_SHA256SU1, "SHA256SU1", "111100110D10nnnndddd1100NQM0mmmm") // v8
|
||||
|
||||
// Three registers of different lengths
|
||||
INST(asimd_VADDL, "VADDL/VADDW", "1111001U1Dzznnnndddd000oN0M0mmmm") // ASIMD
|
||||
INST(asimd_VSUBL, "VSUBL/VSUBW", "1111001U1Dzznnnndddd001oN0M0mmmm") // ASIMD
|
||||
//INST(asimd_VADDHN, "VADDHN", "111100101-----------0100-0-0----") // ASIMD
|
||||
//INST(asimd_VRADDHN, "VRADDHN", "111100111-----------0100-0-0----") // ASIMD
|
||||
INST(asimd_VABAL, "VABAL", "1111001U1Dzznnnndddd0101N0M0mmmm") // ASIMD
|
||||
//INST(asimd_VSUBHN, "VSUBHN", "111100101-----------0110-0-0----") // ASIMD
|
||||
//INST(asimd_VRSUBHN, "VRSUBHN", "111100111-----------0110-0-0----") // ASIMD
|
||||
INST(asimd_VABDL, "VABDL", "1111001U1Dzznnnndddd0111N0M0mmmm") // ASIMD
|
||||
INST(asimd_VMLAL, "VMLAL/VMLSL", "1111001U1Dzznnnndddd10o0N0M0mmmm") // ASIMD
|
||||
//INST(asimd_VQDMLAL, "VQDMLAL", "111100101-----------10-1-0-0----") // ASIMD
|
||||
INST(asimd_VMULL, "VMULL", "1111001U1Dzznnnndddd11P0N0M0mmmm") // ASIMD
|
||||
//INST(asimd_VQDMULL, "VQDMULL", "111100101-----------1101-0-0----") // ASIMD
|
||||
|
||||
// Two registers and a scalar
|
||||
INST(asimd_VMLA_scalar, "VMLA (scalar)", "1111001Q1Dzznnnndddd0o0FN1M0mmmm") // ASIMD
|
||||
INST(asimd_VMLAL_scalar, "VMLAL (scalar)", "1111001U1dzznnnndddd0o10N1M0mmmm") // ASIMD
|
||||
//INST(asimd_VQDMLAL_scalar, "VQDMLAL/VQDMLSL (scalar)", "111100101-BB--------0x11-1-0----") // ASIMD
|
||||
INST(asimd_VMUL_scalar, "VMUL (scalar)", "1111001Q1Dzznnnndddd100FN1M0mmmm") // ASIMD
|
||||
INST(asimd_VMULL_scalar, "VMULL (scalar)", "1111001U1Dzznnnndddd1010N1M0mmmm") // ASIMD
|
||||
INST(asimd_VQDMULL_scalar, "VQDMULL (scalar)", "111100101Dzznnnndddd1011N1M0mmmm") // ASIMD
|
||||
INST(asimd_VQDMULH_scalar, "VQDMULH (scalar)", "1111001Q1Dzznnnndddd1100N1M0mmmm") // ASIMD
|
||||
INST(asimd_VQRDMULH_scalar, "VQRDMULH (scalar)", "1111001Q1Dzznnnndddd1101N1M0mmmm") // ASIMD
|
||||
|
||||
// Two registers and a shift amount
|
||||
INST(asimd_SHR, "SHR", "1111001U1Diiiiiidddd0000LQM1mmmm") // ASIMD
|
||||
INST(asimd_SRA, "SRA", "1111001U1Diiiiiidddd0001LQM1mmmm") // ASIMD
|
||||
INST(asimd_VRSHR, "VRSHR", "1111001U1Diiiiiidddd0010LQM1mmmm") // ASIMD
|
||||
INST(asimd_VRSRA, "VRSRA", "1111001U1Diiiiiidddd0011LQM1mmmm") // ASIMD
|
||||
INST(asimd_VSRI, "VSRI", "111100111Diiiiiidddd0100LQM1mmmm") // ASIMD
|
||||
INST(asimd_VSHL, "VSHL", "111100101Diiiiiidddd0101LQM1mmmm") // ASIMD
|
||||
INST(asimd_VSLI, "VSLI", "111100111Diiiiiidddd0101LQM1mmmm") // ASIMD
|
||||
INST(asimd_VQSHL, "VQSHL" , "1111001U1Diiiiiidddd011oLQM1mmmm") // ASIMD
|
||||
INST(asimd_VSHRN, "VSHRN", "111100101Diiiiiidddd100000M1mmmm") // ASIMD
|
||||
INST(asimd_VRSHRN, "VRSHRN", "111100101Diiiiiidddd100001M1mmmm") // ASIMD
|
||||
INST(asimd_VQSHRUN, "VQSHRUN", "111100111Diiiiiidddd100000M1mmmm") // ASIMD
|
||||
INST(asimd_VQRSHRUN, "VQRSHRUN", "111100111Diiiiiidddd100001M1mmmm") // ASIMD
|
||||
INST(asimd_VQSHRN, "VQSHRN", "1111001U1Diiiiiidddd100100M1mmmm") // ASIMD
|
||||
INST(asimd_VQRSHRN, "VQRSHRN", "1111001U1Diiiiiidddd100101M1mmmm") // ASIMD
|
||||
INST(asimd_VSHLL, "VSHLL", "1111001U1Diiiiiidddd101000M1mmmm") // ASIMD
|
||||
INST(asimd_VCVT_fixed, "VCVT (fixed-point)", "1111001U1Diiiiiidddd111o0QM1mmmm") // ASIMD
|
||||
|
||||
// Two registers, miscellaneous
|
||||
INST(asimd_VREV, "VREV{16,32,64}", "111100111D11zz00dddd000ooQM0mmmm") // ASIMD
|
||||
INST(asimd_VPADDL, "VPADDL", "111100111D11zz00dddd0010oQM0mmmm") // ASIMD
|
||||
INST(asimd_VCLS, "VCLS", "111100111D11zz00dddd01000QM0mmmm") // ASIMD
|
||||
INST(asimd_VCLZ, "VCLZ", "111100111D11zz00dddd01001QM0mmmm") // ASIMD
|
||||
INST(asimd_VCNT, "VCNT", "111100111D11zz00dddd01010QM0mmmm") // ASIMD
|
||||
INST(asimd_VMVN_reg, "VMVN_reg", "111100111D11zz00dddd01011QM0mmmm") // ASIMD
|
||||
INST(asimd_VPADAL, "VPADAL", "111100111D11zz00dddd0110oQM0mmmm") // ASIMD
|
||||
INST(asimd_VQABS, "VQABS", "111100111D11zz00dddd01110QM0mmmm") // ASIMD
|
||||
INST(asimd_VQNEG, "VQNEG", "111100111D11zz00dddd01111QM0mmmm") // ASIMD
|
||||
INST(asimd_VCGT_zero, "VCGT (zero)", "111100111D11zz01dddd0F000QM0mmmm") // ASIMD
|
||||
INST(asimd_VCGE_zero, "VCGE (zero)", "111100111D11zz01dddd0F001QM0mmmm") // ASIMD
|
||||
INST(asimd_VCEQ_zero, "VCEQ (zero)", "111100111D11zz01dddd0F010QM0mmmm") // ASIMD
|
||||
INST(asimd_VCLE_zero, "VCLE (zero)", "111100111D11zz01dddd0F011QM0mmmm") // ASIMD
|
||||
INST(asimd_VCLT_zero, "VCLT (zero)", "111100111D11zz01dddd0F100QM0mmmm") // ASIMD
|
||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--01----01101--0----") // v8
|
||||
INST(asimd_VABS, "VABS", "111100111D11zz01dddd0F110QM0mmmm") // ASIMD
|
||||
INST(asimd_VNEG, "VNEG", "111100111D11zz01dddd0F111QM0mmmm") // ASIMD
|
||||
INST(asimd_VSWP, "VSWP", "111100111D110010dddd00000QM0mmmm") // ASIMD
|
||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--10----00000--0----") // ASIMD
|
||||
INST(asimd_VTRN, "VTRN", "111100111D11zz10dddd00001QM0mmmm") // ASIMD
|
||||
INST(asimd_VUZP, "VUZP", "111100111D11zz10dddd00010QM0mmmm") // ASIMD
|
||||
INST(asimd_VZIP, "VZIP", "111100111D11zz10dddd00011QM0mmmm") // ASIMD
|
||||
INST(asimd_VMOVN, "VMOVN", "111100111D11zz10dddd001000M0mmmm") // ASIMD
|
||||
INST(asimd_VQMOVUN, "VQMOVUN", "111100111D11zz10dddd001001M0mmmm") // ASIMD
|
||||
INST(asimd_VQMOVN, "VQMOVN", "111100111D11zz10dddd00101oM0mmmm") // ASIMD
|
||||
INST(asimd_VSHLL_max, "VSHLL_max", "111100111D11zz10dddd001100M0mmmm") // ASIMD
|
||||
INST(v8_VRINTN, "VRINTN", "111100111D11zz10dddd01000QM0mmmm") // v8
|
||||
INST(v8_VRINTX, "VRINTX", "111100111D11zz10dddd01001QM0mmmm") // v8
|
||||
INST(v8_VRINTA, "VRINTA", "111100111D11zz10dddd01010QM0mmmm") // v8
|
||||
INST(v8_VRINTZ, "VRINTZ", "111100111D11zz10dddd01011QM0mmmm") // v8
|
||||
INST(v8_VRINTM, "VRINTM", "111100111D11zz10dddd01101QM0mmmm") // v8
|
||||
INST(v8_VRINTP, "VRINTP", "111100111D11zz10dddd01111QM0mmmm") // v8
|
||||
INST(asimd_VCVT_half, "VCVT (half-precision)", "111100111D11zz10dddd011o00M0mmmm") // ASIMD
|
||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--10----011-01-0----") // ASIMD
|
||||
INST(v8_VCVTA, "VCVTA", "111100111D11zz11dddd0000oQM0mmmm") // v8
|
||||
INST(v8_VCVTN, "VCVTN", "111100111D11zz11dddd0001oQM0mmmm") // v8
|
||||
INST(v8_VCVTP, "VCVTP", "111100111D11zz11dddd0010oQM0mmmm") // v8
|
||||
INST(v8_VCVTM, "VCVTM", "111100111D11zz11dddd0011oQM0mmmm") // v8
|
||||
INST(asimd_VRECPE, "VRECPE", "111100111D11zz11dddd010F0QM0mmmm") // ASIMD
|
||||
INST(asimd_VRSQRTE, "VRSQRTE", "111100111D11zz11dddd010F1QM0mmmm") // ASIMD
|
||||
INST(asimd_VCVT_integer, "VCVT (integer)", "111100111D11zz11dddd011oUQM0mmmm") // ASIMD
|
||||
|
||||
// Two registers, cryptography
|
||||
INST(v8_AESE, "AESE", "111100111D11zz00dddd001100M0mmmm") // v8
|
||||
INST(v8_AESD, "AESD", "111100111D11zz00dddd001101M0mmmm") // v8
|
||||
INST(v8_AESMC, "AESMC", "111100111D11zz00dddd001110M0mmmm") // v8
|
||||
INST(v8_AESIMC, "AESIMC", "111100111D11zz00dddd001111M0mmmm") // v8
|
||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--01----001010-0----") // v8
|
||||
INST(arm_UDF, "UNALLOCATED (SHA1H)", "111100111-11--01----001011-0----") // v8
|
||||
INST(arm_UDF, "UNALLOCATED (SHA1SU1)", "111100111-11--10----001110-0----") // v8
|
||||
INST(v8_SHA256SU0, "SHA256SU0", "111100111D11zz10dddd001111M0mmmm") // v8
|
||||
|
||||
// One register and modified immediate
|
||||
INST(asimd_VMOV_imm, "VBIC, VMOV, VMVN, VORR (immediate)", "1111001a1D000bcdVVVVmmmm0Qo1efgh") // ASIMD
|
||||
|
||||
// Miscellaneous
|
||||
INST(asimd_VEXT, "VEXT", "111100101D11nnnnddddiiiiNQM0mmmm") // ASIMD
|
||||
INST(asimd_VTBL, "VTBL", "111100111D11nnnndddd10zzN0M0mmmm") // ASIMD
|
||||
INST(asimd_VTBX, "VTBX", "111100111D11nnnndddd10zzN1M0mmmm") // ASIMD
|
||||
INST(asimd_VDUP_scalar, "VDUP (scalar)", "111100111D11iiiidddd11000QM0mmmm") // ASIMD
|
||||
INST(arm_UDF, "UNALLOCATED", "111100111-11--------11-----0----") // ASIMD
|
||||
|
||||
// Advanced SIMD load/store structures
|
||||
INST(v8_VST_multiple, "VST{1-4} (multiple)", "111101000D00nnnnddddxxxxzzaammmm") // v8
|
||||
INST(v8_VLD_multiple, "VLD{1-4} (multiple)", "111101000D10nnnnddddxxxxzzaammmm") // v8
|
||||
INST(arm_UDF, "UNALLOCATED", "111101000--0--------1011--------") // v8
|
||||
INST(arm_UDF, "UNALLOCATED", "111101000--0--------11----------") // v8
|
||||
INST(arm_UDF, "UNALLOCATED", "111101001-00--------11----------") // v8
|
||||
INST(v8_VLD_all_lanes, "VLD{1-4} (all lanes)", "111101001D10nnnndddd11nnzzTammmm") // v8
|
||||
INST(v8_VST_single, "VST{1-4} (single)", "111101001D00nnnnddddzzNNaaaammmm") // v8
|
||||
INST(v8_VLD_single, "VLD{1-4} (single)", "111101001D10nnnnddddzzNNaaaammmm") // v8
|
||||
@@ -0,0 +1,39 @@
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2016 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/frontend/decoder/decoder_detail.h"
|
||||
#include "dynarmic/frontend/decoder/matcher.h"
|
||||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
template<typename Visitor>
|
||||
using Thumb16Matcher = Decoder::Matcher<Visitor, u16>;
|
||||
|
||||
template<typename V>
|
||||
std::optional<std::reference_wrapper<const Thumb16Matcher<V>>> DecodeThumb16(u16 instruction) {
|
||||
static const std::vector<Thumb16Matcher<V>> table = {
|
||||
|
||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(Thumb16Matcher, fn, name, Decoder::detail::StringToArray<16>(bitstring)),
|
||||
#include "./thumb16.inc"
|
||||
#undef INST
|
||||
|
||||
};
|
||||
|
||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||
|
||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||
return iter != table.end() ? std::optional<std::reference_wrapper<const Thumb16Matcher<V>>>(*iter) : std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
@@ -0,0 +1,98 @@
|
||||
// Shift (immediate) add, subtract, move and compare instructions
|
||||
INST(thumb16_LSL_imm, "LSL (imm)", "00000vvvvvmmmddd")
|
||||
INST(thumb16_LSR_imm, "LSR (imm)", "00001vvvvvmmmddd")
|
||||
INST(thumb16_ASR_imm, "ASR (imm)", "00010vvvvvmmmddd")
|
||||
INST(thumb16_ADD_reg_t1, "ADD (reg, T1)", "0001100mmmnnnddd")
|
||||
INST(thumb16_SUB_reg, "SUB (reg)", "0001101mmmnnnddd")
|
||||
INST(thumb16_ADD_imm_t1, "ADD (imm, T1)", "0001110vvvnnnddd")
|
||||
INST(thumb16_SUB_imm_t1, "SUB (imm, T1)", "0001111vvvnnnddd")
|
||||
INST(thumb16_MOV_imm, "MOV (imm)", "00100dddvvvvvvvv")
|
||||
INST(thumb16_CMP_imm, "CMP (imm)", "00101nnnvvvvvvvv")
|
||||
INST(thumb16_ADD_imm_t2, "ADD (imm, T2)", "00110dddvvvvvvvv")
|
||||
INST(thumb16_SUB_imm_t2, "SUB (imm, T2)", "00111dddvvvvvvvv")
|
||||
|
||||
// Data-processing instructions
|
||||
INST(thumb16_AND_reg, "AND (reg)", "0100000000mmmddd")
|
||||
INST(thumb16_EOR_reg, "EOR (reg)", "0100000001mmmddd")
|
||||
INST(thumb16_LSL_reg, "LSL (reg)", "0100000010mmmddd")
|
||||
INST(thumb16_LSR_reg, "LSR (reg)", "0100000011mmmddd")
|
||||
INST(thumb16_ASR_reg, "ASR (reg)", "0100000100mmmddd")
|
||||
INST(thumb16_ADC_reg, "ADC (reg)", "0100000101mmmddd")
|
||||
INST(thumb16_SBC_reg, "SBC (reg)", "0100000110mmmddd")
|
||||
INST(thumb16_ROR_reg, "ROR (reg)", "0100000111sssddd")
|
||||
INST(thumb16_TST_reg, "TST (reg)", "0100001000mmmnnn")
|
||||
INST(thumb16_RSB_imm, "RSB (imm)", "0100001001nnnddd")
|
||||
INST(thumb16_CMP_reg_t1, "CMP (reg, T1)", "0100001010mmmnnn")
|
||||
INST(thumb16_CMN_reg, "CMN (reg)", "0100001011mmmnnn")
|
||||
INST(thumb16_ORR_reg, "ORR (reg)", "0100001100mmmddd")
|
||||
INST(thumb16_MUL_reg, "MUL (reg)", "0100001101nnnddd")
|
||||
INST(thumb16_BIC_reg, "BIC (reg)", "0100001110mmmddd")
|
||||
INST(thumb16_MVN_reg, "MVN (reg)", "0100001111mmmddd")
|
||||
|
||||
// Special data instructions
|
||||
INST(thumb16_ADD_reg_t2, "ADD (reg, T2)", "01000100Dmmmmddd") // v4T, Low regs: v6T2
|
||||
INST(thumb16_CMP_reg_t2, "CMP (reg, T2)", "01000101Nmmmmnnn") // v4T
|
||||
INST(thumb16_MOV_reg, "MOV (reg)", "01000110Dmmmmddd") // v4T, Low regs: v6
|
||||
|
||||
// Store/Load single data item instructions
|
||||
INST(thumb16_LDR_literal, "LDR (literal)", "01001tttvvvvvvvv")
|
||||
INST(thumb16_STR_reg, "STR (reg)", "0101000mmmnnnttt")
|
||||
INST(thumb16_STRH_reg, "STRH (reg)", "0101001mmmnnnttt")
|
||||
INST(thumb16_STRB_reg, "STRB (reg)", "0101010mmmnnnttt")
|
||||
INST(thumb16_LDRSB_reg, "LDRSB (reg)", "0101011mmmnnnttt")
|
||||
INST(thumb16_LDR_reg, "LDR (reg)", "0101100mmmnnnttt")
|
||||
INST(thumb16_LDRH_reg, "LDRH (reg)", "0101101mmmnnnttt")
|
||||
INST(thumb16_LDRB_reg, "LDRB (reg)", "0101110mmmnnnttt")
|
||||
INST(thumb16_LDRSH_reg, "LDRSH (reg)", "0101111mmmnnnttt")
|
||||
INST(thumb16_STR_imm_t1, "STR (imm, T1)", "01100vvvvvnnnttt")
|
||||
INST(thumb16_LDR_imm_t1, "LDR (imm, T1)", "01101vvvvvnnnttt")
|
||||
INST(thumb16_STRB_imm, "STRB (imm)", "01110vvvvvnnnttt")
|
||||
INST(thumb16_LDRB_imm, "LDRB (imm)", "01111vvvvvnnnttt")
|
||||
INST(thumb16_STRH_imm, "STRH (imm)", "10000vvvvvnnnttt")
|
||||
INST(thumb16_LDRH_imm, "LDRH (imm)", "10001vvvvvnnnttt")
|
||||
INST(thumb16_STR_imm_t2, "STR (imm, T2)", "10010tttvvvvvvvv")
|
||||
INST(thumb16_LDR_imm_t2, "LDR (imm, T2)", "10011tttvvvvvvvv")
|
||||
|
||||
// Generate relative address instructions
|
||||
INST(thumb16_ADR, "ADR", "10100dddvvvvvvvv")
|
||||
INST(thumb16_ADD_sp_t1, "ADD (SP plus imm, T1)", "10101dddvvvvvvvv")
|
||||
INST(thumb16_ADD_sp_t2, "ADD (SP plus imm, T2)", "101100000vvvvvvv") // v4T
|
||||
INST(thumb16_SUB_sp, "SUB (SP minus imm)", "101100001vvvvvvv") // v4T
|
||||
|
||||
// Hint instructions
|
||||
INST(thumb16_SEV, "SEV", "1011111101000000") // v7
|
||||
INST(thumb16_SEVL, "SEVL", "1011111101010000") // v8
|
||||
INST(thumb16_WFE, "WFE", "1011111100100000") // v7
|
||||
INST(thumb16_WFI, "WFI", "1011111100110000") // v7
|
||||
INST(thumb16_YIELD, "YIELD", "1011111100010000") // v7
|
||||
INST(thumb16_NOP, "NOP", "10111111----0000") // v7
|
||||
|
||||
// IT instruction
|
||||
INST(thumb16_IT, "IT", "10111111iiiiiiii") // v7
|
||||
|
||||
// Miscellaneous 16-bit instructions
|
||||
INST(thumb16_SXTH, "SXTH", "1011001000mmmddd") // v6
|
||||
INST(thumb16_SXTB, "SXTB", "1011001001mmmddd") // v6
|
||||
INST(thumb16_UXTH, "UXTH", "1011001010mmmddd") // v6
|
||||
INST(thumb16_UXTB, "UXTB", "1011001011mmmddd") // v6
|
||||
INST(thumb16_PUSH, "PUSH", "1011010Mxxxxxxxx") // v4T
|
||||
INST(thumb16_POP, "POP", "1011110Pxxxxxxxx") // v4T
|
||||
INST(thumb16_SETEND, "SETEND", "101101100101x000") // v6
|
||||
INST(thumb16_CPS, "CPS", "10110110011m0aif") // v6
|
||||
INST(thumb16_REV, "REV", "1011101000mmmddd") // v6
|
||||
INST(thumb16_REV16, "REV16", "1011101001mmmddd") // v6
|
||||
INST(thumb16_REVSH, "REVSH", "1011101011mmmddd") // v6
|
||||
INST(thumb16_BKPT, "BKPT", "10111110xxxxxxxx") // v5
|
||||
|
||||
// Store/Load multiple registers
|
||||
INST(thumb16_STMIA, "STMIA", "11000nnnxxxxxxxx")
|
||||
INST(thumb16_LDMIA, "LDMIA", "11001nnnxxxxxxxx")
|
||||
|
||||
// Branch instructions
|
||||
INST(thumb16_BX, "BX", "010001110mmmm000") // v4T
|
||||
INST(thumb16_BLX_reg, "BLX (reg)", "010001111mmmm000") // v5T
|
||||
INST(thumb16_CBZ_CBNZ, "CBZ/CBNZ", "1011o0i1iiiiinnn") // v6T2
|
||||
INST(thumb16_UDF, "UDF", "11011110--------")
|
||||
INST(thumb16_SVC, "SVC", "11011111xxxxxxxx")
|
||||
INST(thumb16_B_t1, "B (T1)", "1101ccccvvvvvvvv")
|
||||
INST(thumb16_B_t2, "B (T2)", "11100vvvvvvvvvvv")
|
||||
@@ -0,0 +1,38 @@
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2016 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/frontend/decoder/decoder_detail.h"
|
||||
#include "dynarmic/frontend/decoder/matcher.h"
|
||||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
template<typename Visitor>
|
||||
using Thumb32Matcher = Decoder::Matcher<Visitor, u32>;
|
||||
|
||||
template<typename V>
|
||||
std::optional<std::reference_wrapper<const Thumb32Matcher<V>>> DecodeThumb32(u32 instruction) {
|
||||
static const std::vector<Thumb32Matcher<V>> table = {
|
||||
|
||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(Thumb32Matcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||
#include "./thumb32.inc"
|
||||
#undef INST
|
||||
|
||||
};
|
||||
|
||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||
|
||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||
return iter != table.end() ? std::optional<std::reference_wrapper<const Thumb32Matcher<V>>>(*iter) : std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
@@ -0,0 +1,292 @@
|
||||
// Load/Store Multiple
|
||||
//INST(thumb32_SRS_1, "SRS", "1110100000-0--------------------")
|
||||
//INST(thumb32_RFE_2, "RFE", "1110100000-1--------------------")
|
||||
INST(thumb32_STMIA, "STMIA/STMEA", "1110100010W0nnnn0iiiiiiiiiiiiiii")
|
||||
INST(thumb32_POP, "POP", "1110100010111101iiiiiiiiiiiiiiii")
|
||||
INST(thumb32_LDMIA, "LDMIA/LDMFD", "1110100010W1nnnniiiiiiiiiiiiiiii")
|
||||
INST(thumb32_PUSH, "PUSH", "11101001001011010iiiiiiiiiiiiiii")
|
||||
INST(thumb32_STMDB, "STMDB/STMFD", "1110100100W0nnnn0iiiiiiiiiiiiiii")
|
||||
INST(thumb32_LDMDB, "LDMDB/LDMEA", "1110100100W1nnnniiiiiiiiiiiiiiii")
|
||||
//INST(thumb32_SRS_1, "SRS", "1110100110-0--------------------")
|
||||
//INST(thumb32_RFE_2, "RFE", "1110100110-1--------------------")
|
||||
|
||||
// Load/Store Dual, Load/Store Exclusive, Table Branch
|
||||
INST(thumb32_STREX, "STREX", "111010000100nnnnttttddddiiiiiiii")
|
||||
INST(thumb32_LDREX, "LDREX", "111010000101nnnntttt1111iiiiiiii")
|
||||
INST(thumb32_STRD_imm_1, "STRD (imm)", "11101000U110nnnnttttssssiiiiiiii")
|
||||
INST(thumb32_STRD_imm_2, "STRD (imm)", "11101001U1W0nnnnttttssssiiiiiiii")
|
||||
INST(thumb32_LDRD_lit_1, "LDRD (lit)", "11101000U1111111ttttssssiiiiiiii")
|
||||
INST(thumb32_LDRD_lit_2, "LDRD (lit)", "11101001U1W11111ttttssssiiiiiiii")
|
||||
INST(thumb32_LDRD_imm_1, "LDRD (imm)", "11101000U111nnnnttttssssiiiiiiii")
|
||||
INST(thumb32_LDRD_imm_2, "LDRD (imm)", "11101001U1W1nnnnttttssssiiiiiiii")
|
||||
INST(thumb32_STL, "STL", "111010001100nnnntttt111110101111") // v8
|
||||
INST(thumb32_LDA, "LDA", "111010001101nnnntttt111110101111") // v8
|
||||
INST(thumb32_STREXB, "STREXB", "111010001100nnnntttt11110100dddd")
|
||||
INST(thumb32_STREXH, "STREXH", "111010001100nnnntttt11110101dddd")
|
||||
INST(thumb32_STREXD, "STREXD", "111010001100nnnnttttuuuu0111dddd")
|
||||
INST(thumb32_TBB, "TBB", "111010001101nnnn111100000000mmmm")
|
||||
INST(thumb32_TBH, "TBH", "111010001101nnnn111100000001mmmm")
|
||||
INST(thumb32_LDREXB, "LDREXB", "111010001101nnnntttt111101001111")
|
||||
INST(thumb32_LDREXH, "LDREXH", "111010001101nnnntttt111101011111")
|
||||
INST(thumb32_LDREXD, "LDREXD", "111010001101nnnnttttuuuu01111111")
|
||||
|
||||
// Data Processing (Shifted Register)
|
||||
INST(thumb32_TST_reg, "TST (reg)", "111010100001nnnn0vvv1111vvttmmmm")
|
||||
INST(thumb32_AND_reg, "AND (reg)", "11101010000Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_BIC_reg, "BIC (reg)", "11101010001Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_MOV_reg, "MOV (reg)", "11101010010S11110vvvddddvvttmmmm")
|
||||
INST(thumb32_ORR_reg, "ORR (reg)", "11101010010Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_MVN_reg, "MVN (reg)", "11101010011S11110vvvddddvvttmmmm")
|
||||
INST(thumb32_ORN_reg, "ORN (reg)", "11101010011Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_TEQ_reg, "TEQ (reg)", "111010101001nnnn0vvv1111vvttmmmm")
|
||||
INST(thumb32_EOR_reg, "EOR (reg)", "11101010100Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_PKH, "PKH", "111010101100nnnn0vvvddddvvt0mmmm")
|
||||
INST(thumb32_CMN_reg, "CMN (reg)", "111010110001nnnn0vvv1111vvttmmmm")
|
||||
INST(thumb32_ADD_reg, "ADD (reg)", "11101011000Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_ADC_reg, "ADC (reg)", "11101011010Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_SBC_reg, "SBC (reg)", "11101011011Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_CMP_reg, "CMP (reg)", "111010111011nnnn0vvv1111vvttmmmm")
|
||||
INST(thumb32_SUB_reg, "SUB (reg)", "11101011101Snnnn0vvvddddvvttmmmm")
|
||||
INST(thumb32_RSB_reg, "RSB (reg)", "11101011110Snnnn0vvvddddvvttmmmm")
|
||||
|
||||
// Data Processing (Modified Immediate)
|
||||
INST(thumb32_TST_imm, "TST (imm)", "11110v000001nnnn0vvv1111vvvvvvvv")
|
||||
INST(thumb32_AND_imm, "AND (imm)", "11110v00000Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_BIC_imm, "BIC (imm)", "11110v00001Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_MOV_imm, "MOV (imm)", "11110v00010S11110vvvddddvvvvvvvv")
|
||||
INST(thumb32_ORR_imm, "ORR (imm)", "11110v00010Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_MVN_imm, "MVN (imm)", "11110v00011S11110vvvddddvvvvvvvv")
|
||||
INST(thumb32_ORN_imm, "ORN (imm)", "11110v00011Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_TEQ_imm, "TEQ (imm)", "11110v001001nnnn0vvv1111vvvvvvvv")
|
||||
INST(thumb32_EOR_imm, "EOR (imm)", "11110v00100Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_CMN_imm, "CMN (imm)", "11110v010001nnnn0vvv1111vvvvvvvv")
|
||||
INST(thumb32_ADD_imm_1, "ADD (imm)", "11110v01000Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_ADC_imm, "ADC (imm)", "11110v01010Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_SBC_imm, "SBC (imm)", "11110v01011Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_CMP_imm, "CMP (imm)", "11110v011011nnnn0vvv1111vvvvvvvv")
|
||||
INST(thumb32_SUB_imm_1, "SUB (imm)", "11110v01101Snnnn0vvvddddvvvvvvvv")
|
||||
INST(thumb32_RSB_imm, "RSB (imm)", "11110v01110Snnnn0vvvddddvvvvvvvv")
|
||||
|
||||
// Data Processing (Plain Binary Immediate)
|
||||
INST(thumb32_ADR_t3, "ADR", "11110i10000011110iiiddddiiiiiiii")
|
||||
INST(thumb32_ADD_imm_2, "ADD (imm)", "11110i100000nnnn0iiiddddiiiiiiii")
|
||||
INST(thumb32_MOVW_imm, "MOVW (imm)", "11110i100100iiii0iiiddddiiiiiiii")
|
||||
INST(thumb32_ADR_t2, "ADR", "11110i10101011110iiiddddiiiiiiii")
|
||||
INST(thumb32_SUB_imm_2, "SUB (imm)", "11110i101010nnnn0iiiddddiiiiiiii")
|
||||
INST(thumb32_MOVT, "MOVT", "11110i101100iiii0iiiddddiiiiiiii")
|
||||
INST(thumb32_UDF, "Invalid decoding", "11110011-010----0000----0001----")
|
||||
INST(thumb32_SSAT16, "SSAT16", "111100110010nnnn0000dddd0000iiii")
|
||||
INST(thumb32_USAT16, "USAT16", "111100111010nnnn0000dddd0000iiii")
|
||||
INST(thumb32_SSAT, "SSAT", "1111001100s0nnnn0iiiddddii0bbbbb")
|
||||
INST(thumb32_USAT, "USAT", "1111001110s0nnnn0iiiddddii0bbbbb")
|
||||
INST(thumb32_SBFX, "SBFX", "111100110100nnnn0iiiddddii0wwwww")
|
||||
INST(thumb32_BFC, "BFC", "11110011011011110iiiddddii0bbbbb")
|
||||
INST(thumb32_BFI, "BFI", "111100110110nnnn0iiiddddii0bbbbb")
|
||||
INST(thumb32_UBFX, "UBFX", "111100111100nnnn0iiiddddii0wwwww")
|
||||
|
||||
// Branches and Miscellaneous Control
|
||||
//INST(thumb32_MSR_banked, "MSR (banked)", "11110011100-----10-0------1-----")
|
||||
INST(thumb32_MSR_reg, "MSR (reg)", "11110011100Rnnnn1000mmmm00000000")
|
||||
|
||||
INST(thumb32_NOP, "NOP", "11110011101011111000000000000000")
|
||||
INST(thumb32_YIELD, "YIELD", "11110011101011111000000000000001")
|
||||
INST(thumb32_WFE, "WFE", "11110011101011111000000000000010")
|
||||
INST(thumb32_WFI, "WFI", "11110011101011111000000000000011")
|
||||
INST(thumb32_SEV, "SEV", "11110011101011111000000000000100")
|
||||
INST(thumb32_SEVL, "SEVL", "11110011101011111000000000000101")
|
||||
//INST(thumb32_DBG, "DBG", "111100111010----10-0-0001111----")
|
||||
//INST(thumb32_CPS, "CPS", "111100111010----10-0------------")
|
||||
|
||||
//INST(thumb32_ENTERX, "ENTERX", "111100111011----10-0----0001----")
|
||||
//INST(thumb32_LEAVEX, "LEAVEX", "111100111011----10-0----0000----")
|
||||
INST(thumb32_CLREX, "CLREX", "11110011101111111000111100101111")
|
||||
INST(thumb32_DSB, "DSB", "1111001110111111100011110100oooo")
|
||||
INST(thumb32_DMB, "DMB", "1111001110111111100011110101oooo")
|
||||
INST(thumb32_ISB, "ISB", "1111001110111111100011110110oooo")
|
||||
|
||||
INST(thumb32_BXJ, "BXJ", "111100111100mmmm1000111100000000")
|
||||
//INST(thumb32_ERET, "ERET", "11110011110111101000111100000000")
|
||||
//INST(thumb32_SUBS_pc_lr, "SUBS PC, LR", "111100111101111010001111--------")
|
||||
|
||||
//INST(thumb32_MRS_banked, "MRS (banked)", "11110011111-----10-0------1-----")
|
||||
INST(thumb32_MRS_reg, "MRS (reg)", "11110011111R11111000dddd00000000")
|
||||
//INST(thumb32_HVC, "HVC", "111101111110----1000------------")
|
||||
//INST(thumb32_SMC, "SMC", "111101111111----1000000000000000")
|
||||
INST(thumb32_UDF, "UDF", "111101111111----1010------------") // v6T2
|
||||
|
||||
// Branch instructions
|
||||
INST(thumb32_BL_imm, "BL (imm)", "11110Svvvvvvvvvv11j1jvvvvvvvvvvv") // v4T
|
||||
INST(thumb32_BLX_imm, "BLX (imm)", "11110Svvvvvvvvvv11j0jvvvvvvvvvvv") // v5T
|
||||
INST(thumb32_B, "B", "11110Svvvvvvvvvv10j1jvvvvvvvvvvv")
|
||||
INST(thumb32_UDF, "Invalid decoding", "11110-111-------10-0------------")
|
||||
INST(thumb32_B_cond, "B (cond)", "11110Sccccvvvvvv10i0ivvvvvvvvvvv")
|
||||
|
||||
// Store Single Data Item
|
||||
INST(thumb32_STRB_imm_1, "STRB (imm)", "111110000000nnnntttt1PU1iiiiiiii")
|
||||
INST(thumb32_STRB_imm_2, "STRB (imm)", "111110000000nnnntttt1100iiiiiiii")
|
||||
INST(thumb32_STRB_imm_3, "STRB (imm)", "111110001000nnnnttttiiiiiiiiiiii")
|
||||
INST(thumb32_STRBT, "STRBT", "111110000000nnnntttt1110iiiiiiii")
|
||||
INST(thumb32_STRB, "STRB (reg)", "111110000000nnnntttt000000iimmmm")
|
||||
INST(thumb32_STRH_imm_1, "STRH (imm)", "111110000010nnnntttt1PU1iiiiiiii")
|
||||
INST(thumb32_STRH_imm_2, "STRH (imm)", "111110000010nnnntttt1100iiiiiiii")
|
||||
INST(thumb32_STRH_imm_3, "STRH (imm)", "111110001010nnnnttttiiiiiiiiiiii")
|
||||
INST(thumb32_STRHT, "STRHT", "111110000010nnnntttt1110iiiiiiii")
|
||||
INST(thumb32_STRH, "STRH (reg)", "111110000010nnnntttt000000iimmmm")
|
||||
INST(thumb32_STR_imm_1, "STR (imm)", "111110000100nnnntttt1PU1iiiiiiii")
|
||||
INST(thumb32_STR_imm_2, "STR (imm)", "111110000100nnnntttt1100iiiiiiii")
|
||||
INST(thumb32_STR_imm_3, "STR (imm)", "111110001100nnnnttttiiiiiiiiiiii")
|
||||
INST(thumb32_STRT, "STRT", "111110000100nnnntttt1110iiiiiiii")
|
||||
INST(thumb32_STR_reg, "STR (reg)", "111110000100nnnntttt000000iimmmm")
|
||||
|
||||
// Load Byte and Memory Hints
|
||||
INST(thumb32_PLD_lit, "PLD (lit)", "11111000U00111111111iiiiiiiiiiii")
|
||||
INST(thumb32_PLD_lit, "PLD (lit)", "11111000U01111111111iiiiiiiiiiii")
|
||||
INST(thumb32_PLD_reg, "PLD (reg)", "1111100000W1nnnn1111000000iimmmm")
|
||||
INST(thumb32_PLD_imm8, "PLD (imm8)", "1111100000W1nnnn11111100iiiiiiii")
|
||||
INST(thumb32_PLD_imm12, "PLD (imm12)", "1111100010W1nnnn1111iiiiiiiiiiii")
|
||||
INST(thumb32_PLI_lit, "PLI (lit)", "11111001U00111111111iiiiiiiiiiii")
|
||||
INST(thumb32_PLI_reg, "PLI (reg)", "111110010001nnnn1111000000iimmmm")
|
||||
INST(thumb32_PLI_imm8, "PLI (imm8)", "111110010001nnnn11111100iiiiiiii")
|
||||
INST(thumb32_PLI_imm12, "PLI (imm12)", "111110011001nnnn1111iiiiiiiiiiii")
|
||||
INST(thumb32_LDRB_lit, "LDRB (lit)", "11111000U0011111ttttiiiiiiiiiiii")
|
||||
INST(thumb32_LDRB_reg, "LDRB (reg)", "111110000001nnnntttt000000iimmmm")
|
||||
INST(thumb32_LDRBT, "LDRBT", "111110000001nnnntttt1110iiiiiiii")
|
||||
INST(thumb32_LDRB_imm8, "LDRB (imm8)", "111110000001nnnntttt1PUWiiiiiiii")
|
||||
INST(thumb32_LDRB_imm12, "LDRB (imm12)", "111110001001nnnnttttiiiiiiiiiiii")
|
||||
INST(thumb32_LDRSB_lit, "LDRSB (lit)", "11111001U0011111ttttiiiiiiiiiiii")
|
||||
INST(thumb32_LDRSB_reg, "LDRSB (reg)", "111110010001nnnntttt000000iimmmm")
|
||||
INST(thumb32_LDRSBT, "LDRSBT", "111110010001nnnntttt1110iiiiiiii")
|
||||
INST(thumb32_LDRSB_imm8, "LDRSB (imm8)", "111110010001nnnntttt1PUWiiiiiiii")
|
||||
INST(thumb32_LDRSB_imm12, "LDRSB (imm12)", "111110011001nnnnttttiiiiiiiiiiii")
|
||||
|
||||
// Load Halfword and Memory Hints
|
||||
INST(thumb32_LDRH_lit, "LDRH (lit)", "11111000U0111111ttttiiiiiiiiiiii")
|
||||
INST(thumb32_LDRH_reg, "LDRH (reg)", "111110000011nnnntttt000000iimmmm")
|
||||
INST(thumb32_LDRHT, "LDRHT", "111110000011nnnntttt1110iiiiiiii")
|
||||
INST(thumb32_LDRH_imm8, "LDRH (imm8)", "111110000011nnnntttt1PUWiiiiiiii")
|
||||
INST(thumb32_LDRH_imm12, "LDRH (imm12)", "111110001011nnnnttttiiiiiiiiiiii")
|
||||
INST(thumb32_NOP, "NOP", "11111001-01111111111------------")
|
||||
INST(thumb32_LDRSH_lit, "LDRSH (lit)", "11111001U0111111ttttiiiiiiiiiiii")
|
||||
INST(thumb32_NOP, "NOP", "111110010011----1111000000------")
|
||||
INST(thumb32_LDRSH_reg, "LDRSH (reg)", "111110010011nnnntttt000000iimmmm")
|
||||
INST(thumb32_LDRSHT, "LDRSHT", "111110010011nnnntttt1110iiiiiiii")
|
||||
INST(thumb32_NOP, "NOP", "111110010011----11111100--------")
|
||||
INST(thumb32_NOP, "NOP", "111110011011----1111------------")
|
||||
INST(thumb32_LDRSH_imm8, "LDRSH (imm8)", "111110010011nnnntttt1PUWiiiiiiii")
|
||||
INST(thumb32_LDRSH_imm12, "LDRSH (imm12)", "111110011011nnnnttttiiiiiiiiiiii")
|
||||
|
||||
// Load Word
|
||||
INST(thumb32_LDR_lit, "LDR (lit)", "11111000U1011111ttttiiiiiiiiiiii")
|
||||
INST(thumb32_LDRT, "LDRT", "111110000101nnnntttt1110iiiiiiii")
|
||||
INST(thumb32_LDR_reg, "LDR (reg)", "111110000101nnnntttt000000iimmmm")
|
||||
INST(thumb32_LDR_imm8, "LDR (imm8)", "111110000101nnnntttt1PUWiiiiiiii")
|
||||
INST(thumb32_LDR_imm12, "LDR (imm12)", "111110001101nnnnttttiiiiiiiiiiii")
|
||||
|
||||
// Data Processing (register)
|
||||
INST(thumb32_LSL_reg, "LSL (reg)", "11111010000Smmmm1111dddd0000ssss")
|
||||
INST(thumb32_LSR_reg, "LSR (reg)", "11111010001Smmmm1111dddd0000ssss")
|
||||
INST(thumb32_ASR_reg, "ASR (reg)", "11111010010Smmmm1111dddd0000ssss")
|
||||
INST(thumb32_ROR_reg, "ROR (reg)", "11111010011Smmmm1111dddd0000ssss")
|
||||
INST(thumb32_SXTH, "SXTH", "11111010000011111111dddd10rrmmmm")
|
||||
INST(thumb32_SXTAH, "SXTAH", "111110100000nnnn1111dddd10rrmmmm")
|
||||
INST(thumb32_UXTH, "UXTH", "11111010000111111111dddd10rrmmmm")
|
||||
INST(thumb32_UXTAH, "UXTAH", "111110100001nnnn1111dddd10rrmmmm")
|
||||
INST(thumb32_SXTB16, "SXTB16", "11111010001011111111dddd10rrmmmm")
|
||||
INST(thumb32_SXTAB16, "SXTAB16", "111110100010nnnn1111dddd10rrmmmm")
|
||||
INST(thumb32_UXTB16, "UXTB16", "11111010001111111111dddd10rrmmmm")
|
||||
INST(thumb32_UXTAB16, "UXTAB16", "111110100011nnnn1111dddd10rrmmmm")
|
||||
INST(thumb32_SXTB, "SXTB", "11111010010011111111dddd10rrmmmm")
|
||||
INST(thumb32_SXTAB, "SXTAB", "111110100100nnnn1111dddd10rrmmmm")
|
||||
INST(thumb32_UXTB, "UXTB", "11111010010111111111dddd10rrmmmm")
|
||||
INST(thumb32_UXTAB, "UXTAB", "111110100101nnnn1111dddd10rrmmmm")
|
||||
|
||||
// Parallel Addition and Subtraction (signed)
|
||||
INST(thumb32_SADD16, "SADD16", "111110101001nnnn1111dddd0000mmmm")
|
||||
INST(thumb32_SASX, "SASX", "111110101010nnnn1111dddd0000mmmm")
|
||||
INST(thumb32_SSAX, "SSAX", "111110101110nnnn1111dddd0000mmmm")
|
||||
INST(thumb32_SSUB16, "SSUB16", "111110101101nnnn1111dddd0000mmmm")
|
||||
INST(thumb32_SADD8, "SADD8", "111110101000nnnn1111dddd0000mmmm")
|
||||
INST(thumb32_SSUB8, "SSUB8", "111110101100nnnn1111dddd0000mmmm")
|
||||
INST(thumb32_QADD16, "QADD16", "111110101001nnnn1111dddd0001mmmm")
|
||||
INST(thumb32_QASX, "QASX", "111110101010nnnn1111dddd0001mmmm")
|
||||
INST(thumb32_QSAX, "QSAX", "111110101110nnnn1111dddd0001mmmm")
|
||||
INST(thumb32_QSUB16, "QSUB16", "111110101101nnnn1111dddd0001mmmm")
|
||||
INST(thumb32_QADD8, "QADD8", "111110101000nnnn1111dddd0001mmmm")
|
||||
INST(thumb32_QSUB8, "QSUB8", "111110101100nnnn1111dddd0001mmmm")
|
||||
INST(thumb32_SHADD16, "SHADD16", "111110101001nnnn1111dddd0010mmmm")
|
||||
INST(thumb32_SHASX, "SHASX", "111110101010nnnn1111dddd0010mmmm")
|
||||
INST(thumb32_SHSAX, "SHSAX", "111110101110nnnn1111dddd0010mmmm")
|
||||
INST(thumb32_SHSUB16, "SHSUB16", "111110101101nnnn1111dddd0010mmmm")
|
||||
INST(thumb32_SHADD8, "SHADD8", "111110101000nnnn1111dddd0010mmmm")
|
||||
INST(thumb32_SHSUB8, "SHSUB8", "111110101100nnnn1111dddd0010mmmm")
|
||||
|
||||
// Parallel Addition and Subtraction (unsigned)
|
||||
INST(thumb32_UADD16, "UADD16", "111110101001nnnn1111dddd0100mmmm")
|
||||
INST(thumb32_UASX, "UASX", "111110101010nnnn1111dddd0100mmmm")
|
||||
INST(thumb32_USAX, "USAX", "111110101110nnnn1111dddd0100mmmm")
|
||||
INST(thumb32_USUB16, "USUB16", "111110101101nnnn1111dddd0100mmmm")
|
||||
INST(thumb32_UADD8, "UADD8", "111110101000nnnn1111dddd0100mmmm")
|
||||
INST(thumb32_USUB8, "USUB8", "111110101100nnnn1111dddd0100mmmm")
|
||||
INST(thumb32_UQADD16, "UQADD16", "111110101001nnnn1111dddd0101mmmm")
|
||||
INST(thumb32_UQASX, "UQASX", "111110101010nnnn1111dddd0101mmmm")
|
||||
INST(thumb32_UQSAX, "UQSAX", "111110101110nnnn1111dddd0101mmmm")
|
||||
INST(thumb32_UQSUB16, "UQSUB16", "111110101101nnnn1111dddd0101mmmm")
|
||||
INST(thumb32_UQADD8, "UQADD8", "111110101000nnnn1111dddd0101mmmm")
|
||||
INST(thumb32_UQSUB8, "UQSUB8", "111110101100nnnn1111dddd0101mmmm")
|
||||
INST(thumb32_UHADD16, "UHADD16", "111110101001nnnn1111dddd0110mmmm")
|
||||
INST(thumb32_UHASX, "UHASX", "111110101010nnnn1111dddd0110mmmm")
|
||||
INST(thumb32_UHSAX, "UHSAX", "111110101110nnnn1111dddd0110mmmm")
|
||||
INST(thumb32_UHSUB16, "UHSUB16", "111110101101nnnn1111dddd0110mmmm")
|
||||
INST(thumb32_UHADD8, "UHADD8", "111110101000nnnn1111dddd0110mmmm")
|
||||
INST(thumb32_UHSUB8, "UHSUB8", "111110101100nnnn1111dddd0110mmmm")
|
||||
|
||||
// Miscellaneous Operations
|
||||
INST(thumb32_QADD, "QADD", "111110101000nnnn1111dddd1000mmmm")
|
||||
INST(thumb32_QDADD, "QDADD", "111110101000nnnn1111dddd1001mmmm")
|
||||
INST(thumb32_QSUB, "QSUB", "111110101000nnnn1111dddd1010mmmm")
|
||||
INST(thumb32_QDSUB, "QDSUB", "111110101000nnnn1111dddd1011mmmm")
|
||||
INST(thumb32_REV, "REV", "111110101001nnnn1111dddd1000mmmm")
|
||||
INST(thumb32_REV16, "REV16", "111110101001nnnn1111dddd1001mmmm")
|
||||
INST(thumb32_RBIT, "RBIT", "111110101001nnnn1111dddd1010mmmm")
|
||||
INST(thumb32_REVSH, "REVSH", "111110101001nnnn1111dddd1011mmmm")
|
||||
INST(thumb32_SEL, "SEL", "111110101010nnnn1111dddd1000mmmm")
|
||||
INST(thumb32_CLZ, "CLZ", "111110101011nnnn1111dddd1000mmmm")
|
||||
|
||||
// Multiply, Multiply Accumulate, and Absolute Difference
|
||||
INST(thumb32_MUL, "MUL", "111110110000nnnn1111dddd0000mmmm")
|
||||
INST(thumb32_MLA, "MLA", "111110110000nnnnaaaadddd0000mmmm")
|
||||
INST(thumb32_MLS, "MLS", "111110110000nnnnaaaadddd0001mmmm")
|
||||
INST(thumb32_SMULXY, "SMULXY", "111110110001nnnn1111dddd00NMmmmm")
|
||||
INST(thumb32_SMLAXY, "SMLAXY", "111110110001nnnnaaaadddd00NMmmmm")
|
||||
INST(thumb32_SMUAD, "SMUAD", "111110110010nnnn1111dddd000Mmmmm")
|
||||
INST(thumb32_SMLAD, "SMLAD", "111110110010nnnnaaaadddd000Xmmmm")
|
||||
INST(thumb32_SMULWY, "SMULWY", "111110110011nnnn1111dddd000Mmmmm")
|
||||
INST(thumb32_SMLAWY, "SMLAWY", "111110110011nnnnaaaadddd000Mmmmm")
|
||||
INST(thumb32_SMUSD, "SMUSD", "111110110100nnnn1111dddd000Mmmmm")
|
||||
INST(thumb32_SMLSD, "SMLSD", "111110110100nnnnaaaadddd000Xmmmm")
|
||||
INST(thumb32_SMMUL, "SMMUL", "111110110101nnnn1111dddd000Rmmmm")
|
||||
INST(thumb32_SMMLA, "SMMLA", "111110110101nnnnaaaadddd000Rmmmm")
|
||||
INST(thumb32_SMMLS, "SMMLS", "111110110110nnnnaaaadddd000Rmmmm")
|
||||
INST(thumb32_USAD8, "USAD8", "111110110111nnnn1111dddd0000mmmm")
|
||||
INST(thumb32_USADA8, "USADA8", "111110110111nnnnaaaadddd0000mmmm")
|
||||
|
||||
// Long Multiply, Long Multiply Accumulate, and Divide
|
||||
INST(thumb32_SMULL, "SMULL", "111110111000nnnnllllhhhh0000mmmm")
|
||||
INST(thumb32_SDIV, "SDIV", "111110111001nnnn1111dddd1111mmmm")
|
||||
INST(thumb32_UMULL, "UMULL", "111110111010nnnnllllhhhh0000mmmm")
|
||||
INST(thumb32_UDIV, "UDIV", "111110111011nnnn1111dddd1111mmmm")
|
||||
INST(thumb32_SMLAL, "SMLAL", "111110111100nnnnllllhhhh0000mmmm")
|
||||
INST(thumb32_SMLALXY, "SMLALXY", "111110111100nnnnllllhhhh10NMmmmm")
|
||||
INST(thumb32_SMLALD, "SMLALD", "111110111100nnnnllllhhhh110Mmmmm")
|
||||
INST(thumb32_SMLSLD, "SMLSLD", "111110111101nnnnllllhhhh110Mmmmm")
|
||||
INST(thumb32_UMLAL, "UMLAL", "111110111110nnnnllllhhhh0000mmmm")
|
||||
INST(thumb32_UMAAL, "UMAAL", "111110111110nnnnllllhhhh0110mmmm")
|
||||
|
||||
// Coprocessor
|
||||
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")
|
||||
@@ -0,0 +1,58 @@
|
||||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2032 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/frontend/decoder/decoder_detail.h"
|
||||
#include "dynarmic/frontend/decoder/matcher.h"
|
||||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
template<typename Visitor>
|
||||
using VFPMatcher = Decoder::Matcher<Visitor, u32>;
|
||||
|
||||
template<typename V>
|
||||
std::optional<std::reference_wrapper<const VFPMatcher<V>>> DecodeVFP(u32 instruction) {
|
||||
using Table = std::vector<VFPMatcher<V>>;
|
||||
|
||||
static const struct Tables {
|
||||
Table unconditional;
|
||||
Table conditional;
|
||||
} tables = [] {
|
||||
Table list = {
|
||||
|
||||
#define INST(fn, name, bitstring) DYNARMIC_DECODER_GET_MATCHER(VFPMatcher, fn, name, Decoder::detail::StringToArray<32>(bitstring)),
|
||||
#include "./vfp.inc"
|
||||
#undef INST
|
||||
|
||||
};
|
||||
|
||||
const auto division = std::stable_partition(list.begin(), list.end(), [&](const auto& matcher) {
|
||||
return (matcher.GetMask() & 0xF0000000) == 0xF0000000;
|
||||
});
|
||||
|
||||
return Tables{
|
||||
Table{list.begin(), division},
|
||||
Table{division, list.end()},
|
||||
};
|
||||
}();
|
||||
|
||||
const bool is_unconditional = (instruction & 0xF0000000) == 0xF0000000;
|
||||
const Table& table = is_unconditional ? tables.unconditional : tables.conditional;
|
||||
|
||||
const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
|
||||
|
||||
auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
|
||||
return iter != table.end() ? std::optional<std::reference_wrapper<const VFPMatcher<V>>>(*iter) : std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
@@ -0,0 +1,71 @@
|
||||
// Floating-point three-register data processing instructions
|
||||
INST(vfp_VMLA, "VMLA", "cccc11100D00nnnndddd101zN0M0mmmm") // VFPv2
|
||||
INST(vfp_VMLS, "VMLS", "cccc11100D00nnnndddd101zN1M0mmmm") // VFPv2
|
||||
INST(vfp_VNMLS, "VNMLS", "cccc11100D01nnnndddd101zN0M0mmmm") // VFPv2
|
||||
INST(vfp_VNMLA, "VNMLA", "cccc11100D01nnnndddd101zN1M0mmmm") // VFPv2
|
||||
INST(vfp_VMUL, "VMUL", "cccc11100D10nnnndddd101zN0M0mmmm") // VFPv2
|
||||
INST(vfp_VNMUL, "VNMUL", "cccc11100D10nnnndddd101zN1M0mmmm") // VFPv2
|
||||
INST(vfp_VADD, "VADD", "cccc11100D11nnnndddd101zN0M0mmmm") // VFPv2
|
||||
INST(vfp_VSUB, "VSUB", "cccc11100D11nnnndddd101zN1M0mmmm") // VFPv2
|
||||
INST(vfp_VDIV, "VDIV", "cccc11101D00nnnndddd101zN0M0mmmm") // VFPv2
|
||||
INST(vfp_VFNMS, "VFNMS", "cccc11101D01nnnndddd101zN0M0mmmm") // VFPv4
|
||||
INST(vfp_VFNMA, "VFNMA", "cccc11101D01nnnndddd101zN1M0mmmm") // VFPv4
|
||||
INST(vfp_VFMA, "VFMA", "cccc11101D10nnnndddd101zN0M0mmmm") // VFPv4
|
||||
INST(vfp_VFMS, "VFMS", "cccc11101D10nnnndddd101zN1M0mmmm") // VFPv4
|
||||
INST(vfp_VSEL, "VSEL", "111111100Dccnnnndddd101zN0M0mmmm") // VFPv5
|
||||
INST(vfp_VMAXNM, "VMAXNNM", "111111101D00nnnndddd101zN0M0mmmm") // VFPv5
|
||||
INST(vfp_VMINNM, "VMINNM", "111111101D00nnnndddd101zN1M0mmmm") // VFPv5
|
||||
|
||||
// Other floating-point data-processing instructions
|
||||
INST(vfp_VMOV_imm, "VMOV (immediate)", "cccc11101D11vvvvdddd101z0000vvvv") // VFPv3
|
||||
INST(vfp_VMOV_reg, "VMOV (reg)", "cccc11101D110000dddd101z01M0mmmm") // VFPv2
|
||||
INST(vfp_VABS, "VABS", "cccc11101D110000dddd101z11M0mmmm") // VFPv2
|
||||
INST(vfp_VNEG, "VNEG", "cccc11101D110001dddd101z01M0mmmm") // VFPv2
|
||||
INST(vfp_VSQRT, "VSQRT", "cccc11101D110001dddd101z11M0mmmm") // VFPv2
|
||||
INST(vfp_VCVTB, "VCVTB", "cccc11101D11001odddd101z01M0mmmm") // VFPv3HP
|
||||
INST(vfp_VCVTT, "VCVTT", "cccc11101D11001odddd101z11M0mmmm") // VFPv3HP
|
||||
INST(vfp_VCMP, "VCMP", "cccc11101D110100dddd101zE1M0mmmm") // VFPv2
|
||||
INST(vfp_VCMP_zero, "VCMP (with zero)", "cccc11101D110101dddd101zE1000000") // VFPv2
|
||||
INST(vfp_VRINTR, "VRINTR", "cccc11101D110110dddd101z01M0mmmm") // VFPv5
|
||||
INST(vfp_VRINTZ, "VRINTZ", "cccc11101D110110dddd101z11M0mmmm") // VFPv5
|
||||
INST(vfp_VRINTX, "VRINTX", "cccc11101D110111dddd101z01M0mmmm") // VFPv5
|
||||
INST(vfp_VCVT_f_to_f, "VCVT (f32<->f64)", "cccc11101D110111dddd101z11M0mmmm") // VFPv2
|
||||
INST(vfp_VCVT_from_int, "VCVT (from int)", "cccc11101D111000dddd101zs1M0mmmm") // VFPv2
|
||||
INST(vfp_VCVT_from_fixed, "VCVT (from fixed)", "cccc11101D11101Udddd101zx1i0vvvv") // VFPv3
|
||||
INST(vfp_VCVT_to_u32, "VCVT (to u32)", "cccc11101D111100dddd101zr1M0mmmm") // VFPv2
|
||||
INST(vfp_VCVT_to_s32, "VCVT (to s32)", "cccc11101D111101dddd101zr1M0mmmm") // VFPv2
|
||||
INST(vfp_VCVT_to_fixed, "VCVT (to fixed)", "cccc11101D11111Udddd101zx1i0vvvv") // VFPv3
|
||||
INST(vfp_VRINT_rm, "VRINT{A,N,P,M}", "111111101D1110mmdddd101z01M0mmmm") // VFPv5
|
||||
INST(vfp_VCVT_rm, "VCVT{A,N,P,M}", "111111101D1111mmdddd101zU1M0mmmm") // VFPv5
|
||||
|
||||
// Floating-point move instructions
|
||||
INST(vfp_VMOV_u32_f64, "VMOV (core to f64)", "cccc11100000ddddtttt1011D0010000") // VFPv2
|
||||
INST(vfp_VMOV_f64_u32, "VMOV (f64 to core)", "cccc11100001nnnntttt1011N0010000") // VFPv2
|
||||
INST(vfp_VMOV_u32_f32, "VMOV (core to f32)", "cccc11100000nnnntttt1010N0010000") // VFPv2
|
||||
INST(vfp_VMOV_f32_u32, "VMOV (f32 to core)", "cccc11100001nnnntttt1010N0010000") // VFPv2
|
||||
INST(vfp_VMOV_2u32_2f32, "VMOV (2xcore to 2xf32)", "cccc11000100uuuutttt101000M1mmmm") // VFPv2
|
||||
INST(vfp_VMOV_2f32_2u32, "VMOV (2xf32 to 2xcore)", "cccc11000101uuuutttt101000M1mmmm") // VFPv2
|
||||
INST(vfp_VMOV_2u32_f64, "VMOV (2xcore to f64)", "cccc11000100uuuutttt101100M1mmmm") // VFPv2
|
||||
INST(vfp_VMOV_f64_2u32, "VMOV (f64 to 2xcore)", "cccc11000101uuuutttt101100M1mmmm") // VFPv2
|
||||
INST(vfp_VMOV_from_i32, "VMOV (core to i32)" , "cccc111000i0nnnntttt1011N0010000") // VFPv4
|
||||
INST(vfp_VMOV_from_i16, "VMOV (core to i16)" , "cccc111000i0nnnntttt1011Ni110000") // ASIMD
|
||||
INST(vfp_VMOV_from_i8, "VMOV (core to i8)", "cccc111001i0nnnntttt1011Nii10000") // ASIMD
|
||||
INST(vfp_VMOV_to_i32, "VMOV (i32 to core)" , "cccc111000i1nnnntttt1011N0010000") // VFPv4
|
||||
INST(vfp_VMOV_to_i16, "VMOV (i16 to core)" , "cccc1110U0i1nnnntttt1011Ni110000") // ASIMD
|
||||
INST(vfp_VMOV_to_i8, "VMOV (i8 to core)", "cccc1110U1i1nnnntttt1011Nii10000") // ASIMD
|
||||
INST(vfp_VDUP, "VDUP (from core)", "cccc11101BQ0ddddtttt1011D0E10000") // ASIMD
|
||||
|
||||
// Floating-point system register access
|
||||
INST(vfp_VMSR, "VMSR", "cccc111011100001tttt101000010000") // VFPv2
|
||||
INST(vfp_VMRS, "VMRS", "cccc111011110001tttt101000010000") // VFPv2
|
||||
|
||||
// Extension register load-store instructions
|
||||
INST(vfp_VPUSH, "VPUSH", "cccc11010D101101dddd101zvvvvvvvv") // VFPv2
|
||||
INST(vfp_VPOP, "VPOP", "cccc11001D111101dddd101zvvvvvvvv") // VFPv2
|
||||
INST(vfp_VLDR, "VLDR", "cccc1101UD01nnnndddd101zvvvvvvvv") // VFPv2
|
||||
INST(vfp_VSTR, "VSTR", "cccc1101UD00nnnndddd101zvvvvvvvv") // VFPv2
|
||||
INST(arm_UDF, "Undefined VSTM/VLDM", "----11000-0---------101---------") // VFPv2
|
||||
INST(vfp_VSTM_a1, "VSTM (A1)", "cccc110puDw0nnnndddd1011vvvvvvvv") // VFPv2
|
||||
INST(vfp_VSTM_a2, "VSTM (A2)", "cccc110puDw0nnnndddd1010vvvvvvvv") // VFPv2
|
||||
INST(vfp_VLDM_a1, "VLDM (A1)", "cccc110puDw1nnnndddd1011vvvvvvvv") // VFPv2
|
||||
INST(vfp_VLDM_a2, "VLDM (A2)", "cccc110puDw1nnnndddd1010vvvvvvvv") // VFPv2
|
||||
Reference in New Issue
Block a user