A32: Add decoders for remaining v7 instructions

This commit is contained in:
MerryMage 2020-05-10 10:50:34 +01:00
parent 8b3bc92bce
commit 9a38c7324f
7 changed files with 198 additions and 17 deletions

View file

@ -106,6 +106,8 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS)
target_sources(dynarmic PRIVATE
frontend/A32/decoder/arm.h
frontend/A32/decoder/arm.inc
frontend/A32/decoder/asimd.h
frontend/A32/decoder/asimd.inc
frontend/A32/decoder/thumb16.h
frontend/A32/decoder/thumb32.h
frontend/A32/decoder/vfp.h

View file

@ -0,0 +1,51 @@
/* 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 <vector>
#include "common/bit_util.h"
#include "common/common_types.h"
#include "frontend/decoder/decoder_detail.h"
#include "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) Decoder::detail::detail<ASIMDMatcher<V>>::GetMatcher(&V::fn, name, bitstring),
#include "asimd.inc"
#undef INST
};
// If a matcher has more bits in its mask it is more specific, so it should come first.
std::stable_sort(table.begin(), table.end(), [](const auto& matcher1, const auto& matcher2) {
return Common::BitCount(matcher1.GetMask()) > Common::BitCount(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

View file

@ -0,0 +1,121 @@
// Three registers of the same length
//INST(asimd_VHADD, "VHADD", "1111001U0-CC--------0000---0----") // ASIMD
//INST(asimd_VQADD, "VQADD", "1111001U0-CC--------0000---1----") // ASIMD
//INST(asimd_VRHADD, "VRHADD", "1111001U0-CC--------0001---0----") // ASIMD
//INST(asimd_VAND_reg, "VAND (register)", "111100100-00--------0001---1----") // ASIMD
//INST(asimd_VBIC_reg, "VBIC (register)", "111100100-01--------0001---1----") // ASIMD
//INST(asimd_VORR_reg, "VORR (register)", "111100100-10--------0001---1----") // ASIMD
//INST(asimd_VORN_reg, "VORN (register)", "111100100-11--------0001---1----") // ASIMD
//INST(asimd_VEOR_reg, "VEOR (register)", "111100110-00--------0001---1----") // ASIMD
//INST(asimd_VBSL, "VBSL", "111100110-01--------0001---1----") // ASIMD
//INST(asimd_VBIT, "VBIT", "111100110-10--------0001---1----") // ASIMD
//INST(asimd_VBIF, "VBIF", "111100110-11--------0001---1----") // ASIMD
//INST(asimd_VHADD, "VHADD", "1111001U0-CC--------0010---0----") // ASIMD
//INST(asimd_VQSUB, "VQSUB", "1111001U0-CC--------0010---1----") // ASIMD
//INST(asimd_VCGT_reg, "VCGT (register)", "1111001U0-CC--------0011---0----") // ASIMD
//INST(asimd_VCGE_reg, "VCGE (register)", "1111001U0-CC--------0011---1----") // ASIMD
//INST(asimd_VSHL_reg, "VSHL (register)", "1111001U0-CC--------0100---0----") // ASIMD
//INST(asimd_VQSHL_reg, "VQSHL (register)", "1111001U0-CC--------0100---1----") // ASIMD
//INST(asimd_VRSHL, "VRSHL", "1111001U0-CC--------0101---0----") // ASIMD
//INST(asimd_VQRSHL, "VQRSHL", "1111001U0-CC--------0101---1----") // ASIMD
//INST(asimd_VMAX, "VMAX/VMIN", "1111001U0-CC--------0110---B----") // ASIMD
//INST(asimd_VABD, "VABD/VABDL", "1111001U0-CC--------0111---0----") // ASIMD
//INST(asimd_VABA, "VABA/ABAL", "1111001U0-CC--------0111---1----") // ASIMD
//INST(asimd_VADD_int, "VADD (integer)", "111100100-CC--------1000---0----") // ASIMD
//INST(asimd_VSUB_int, "VAND (integer)", "111100110-CC--------1000---0----") // ASIMD
//INST(asimd_VTST, "VTST", "111100100-CC--------1000---1----") // ASIMD
//INST(asimd_VCEQ_reg, "VCEG (register)", "111100110-CC--------1000---1----") // ASIMD
//INST(asimd_VMLA, "VMLA/VMLAL/VMLS/VMLSL", "1111001U0-CC--------1001---0----") // ASIMD
//INST(asimd_VMUL, "VMUL/VMULL", "1111001U0-CC--------1001---1----") // ASIMD
//INST(asimd_VPMAX, "VPMAX/VPMIN", "1111001U0-CC--------1010---B----") // ASIMD
//INST(asimd_VQDMULH, "VQDMULH", "111100100-CC--------1011---0----") // ASIMD
//INST(asimd_VQRDMULH, "VQRDMULH", "111100110-CC--------1011---0----") // ASIMD
//INST(asimd_VPADD, "VPADD", "1111001U0-CC--------1011---1----") // ASIMD
//INST(asimd_VFMA, "VFMA/VFMS", "111100100-CC--------1100---1----") // ASIMD
//INST(asimd_VADD_float, "VADD (floating-point)", "111100100-0C--------1101---0----") // ASIMD
//INST(asimd_VSUB_float, "VSUB (floating-point)", "111100100-1C--------1101---0----") // ASIMD
//INST(asimd_VPADD_float, "VPADD (floating-point)", "111100110-0C--------1101---0----") // ASIMD
//INST(asimd_VABD_float, "VABD (floating-point)", "111100110-1C--------1101---0----") // ASIMD
//INST(asimd_VMLA_float, "VMLA (floating-point)", "111100100-CC--------1101---1----") // ASIMD
//INST(asimd_VMUL_float, "VMUL (floating-point)", "111100110-0C--------1101---1----") // ASIMD
//INST(asimd_VCEQ_reg, "VCEQ (register)", "111100100-0C--------1110---0----") // ASIMD
//INST(asimd_VCGE_reg, "VCGE (register)", "111100110-0C--------1110---0----") // ASIMD
//INST(asimd_VCGT_reg, "VCGT (register)", "111100110-1C--------1110---0----") // ASIMD
//INST(asimd_VACGE, "VACGE", "111100110-CC--------1110---1----") // ASIMD
//INST(asimd_VMAX_float, "VMAX (floating-point)", "111100100-CC--------1111---0----") // ASIMD
//INST(asimd_VPMAX_float, "VMIN (floating-point)", "111100110-CC--------1111---0----") // ASIMD
//INST(asimd_VRECPS, "VRECPS", "111100100-0C--------1111---1----") // ASIMD
//INST(asimd_VRSQRTS, "VRSQRTS", "111100100-1C--------1111---1----") // ASIMD
// Two registers and a scalar
//INST(asimd_VMLA_scalar, "VMLA (scalar)", "1111001U1-BB--------0x0x-1-0----") // ASIMD
//INST(asimd_VMLAL_scalar, "VMLAL (scalar)", "1111001U1-BB--------0x10-1-0----") // ASIMD
//INST(asimd_VQDMLAL, "VQDMLAL/VQDMLSL", "111100101-BB--------0x11-1-0----") // ASIMD
//INST(asimd_VMUL_scalar, "VMUL (scalar)", "1111001U1-BB--------100x-1-0----") // ASIMD
//INST(asimd_VMULL_scalar, "VMULL (scalar)", "1111001U1-BB--------1010-1-0----") // ASIMD
//INST(asimd_VQDMULL, "VQDMULL", "111100101-BB--------1011-1-0----") // ASIMD
//INST(asimd_VQDMULH, "VQDMULH", "1111001U1-BB--------1100-1-0----") // ASIMD
//INST(asimd_VQRDMULH, "VQRDMULH", "1111001U1-BB--------1101-1-0----") // ASIMD
// Two registers and a shift amount
//INST(asimd_SHR, "SHR", "1111001U1-vvv-------0000LB-1----") // ASIMD
//INST(asimd_SRA, "SRA", "1111001U1-vvv-------0001LB-1----") // ASIMD
//INST(asimd_VRSHR, "VRSHR", "1111001U1-vvv-------0010LB-1----") // ASIMD
//INST(asimd_VRSRA, "VRSRA", "1111001U1-vvv-------0011LB-1----") // ASIMD
//INST(asimd_VSRI, "VSRI", "111100111-vvv-------0100LB-1----") // ASIMD
//INST(asimd_VSHL, "VSHL", "111100101-vvv-------0101LB-1----") // ASIMD
//INST(asimd_VSLI, "VSLI", "111100111-vvv-------0101LB-1----") // ASIMD
//INST(asimd_VQSHL, "VQSHL" , "1111001U1-vvv-------011xLB-1----") // ASIMD
//INST(asimd_VSHRN, "VSHRN", "111100101-vvv-------100000-1----") // ASIMD
//INST(asimd_VRSHRN, "VRSHRN", "111100101-vvv-------100001-1----") // ASIMD
//INST(asimd_VQSHRUN, "VQSHRUN", "111100111-vvv-------100000-1----") // ASIMD
//INST(asimd_VQRSHRUN, "VQRSHRUN", "111100111-vvv-------100001-1----") // ASIMD
//INST(asimd_VQSHRN, "VQSHRN", "1111001U1-vvv-------100100-1----") // ASIMD
//INST(asimd_VQRSHRN, "VQRSHRN", "1111001U1-vvv-------100101-1----") // ASIMD
//INST(asimd_SHLL, "SHLL", "1111001U1-vvv-------101000-1----") // ASIMD
//INST(asimd_VCVT_fixed, "VCVT (fixed-point)", "1111001U1-vvv-------111x0B-1----") // ASIMD
// Two registers, miscellaneous
//INST(asimd_VREV64, "VREV64", "111100111-11--00----00000x-0----") // ASIMD
//INST(asimd_VREV32, "VREV32", "111100111-11--00----00001x-0----") // ASIMD
//INST(asimd_VREV16, "VREV16", "111100111-11--00----00010x-0----") // ASIMD
//INST(asimd_VPADDL, "VPADDL", "111100111-11--00----0010xx-0----") // ASIMD
//INST(asimd_VCLS, "VCLS", "111100111-11--00----01000x-0----") // ASIMD
//INST(asimd_VCLZ, "VCLZ", "111100111-11--00----01001x-0----") // ASIMD
//INST(asimd_VCNT, "VCNT", "111100111-11--00----01010x-0----") // ASIMD
//INST(asimd_VMVN_reg, "VMVN_reg", "111100111-11--00----01011x-0----") // ASIMD
//INST(asimd_VPADAL, "VPADAL", "111100111-11--00----0110xx-0----") // ASIMD
//INST(asimd_VQABS, "VQABS", "111100111-11--00----01110x-0----") // ASIMD
//INST(asimd_VQNEG, "VQNEG", "111100111-11--00----01111x-0----") // ASIMD
//INST(asimd_VCGT_zero, "VCGT (zero)", "111100111-11--01----0x000x-0----") // ASIMD
//INST(asimd_VCGE_zero, "VCGE (zero)", "111100111-11--01----0x001x-0----") // ASIMD
//INST(asimd_VCEQ_zero, "VCEQ (zero)", "111100111-11--01----0x010x-0----") // ASIMD
//INST(asimd_VCLE_zero, "VCLE (zero)", "111100111-11--01----0x011x-0----") // ASIMD
//INST(asimd_VCLT_zero, "VCLT (zero)", "111100111-11--01----0x100x-0----") // ASIMD
//INST(asimd_VABS, "VABS", "111100111-11--01----0x110x-0----") // ASIMD
//INST(asimd_VNEG, "VNEG", "111100111-11--01----0x111x-0----") // ASIMD
//INST(asimd_VSWP, "VSWP", "111100111-11--10----00000x-0----") // ASIMD
//INST(asimd_VTRN, "VTRN", "111100111-11--10----00001x-0----") // ASIMD
//INST(asimd_VUZP, "VUZP", "111100111-11--10----00010x-0----") // ASIMD
//INST(asimd_VZIP, "VZIP", "111100111-11--10----00011x-0----") // ASIMD
//INST(asimd_VMOVN, "VMOVN", "111100111-11--10----001000-0----") // ASIMD
//INST(asimd_VQMOVUN, "VQMOVUN", "111100111-11--10----001001-0----") // ASIMD
//INST(asimd_VQMOVN, "VQMOVN", "111100111-11--10----00101x-0----") // ASIMD
//INST(asimd_VSHLL_max, "VSHLL_max", "111100111-11--10----001100-0----") // ASIMD
//INST(asimd_VCVT_half, "VCVT (half-precision)", "111100111-11--10----011x00-0----") // ASIMD
//INST(asimd_VRECPE, "VRECPE", "111100111-11--11----010x0x-0----") // ASIMD
//INST(asimd_VRSQRTE, "VRSQRTE", "111100111-11--11----010x1x-0----") // ASIMD
//INST(asimd_VCVT_integer, "VCVT (integer)", "111100111-11--11----011xxx-0----") // ASIMD
// One register and modified immediate
//INST(asimd_VMOV_imm, "VMOV (immediate)", "1111001a1-000bcd----0xx00-01efgh") // ASIMD
//INST(asimd_VORR_imm, "VORR (immediate)", "1111001a1-000bcd----0xx10-01efgh") // ASIMD
//INST(asimd_VMOV_imm, "VMOV (immediate)", "1111001a1-000bcd----10x00-01efgh") // ASIMD
//INST(asimd_VORR_imm, "VORR (immediate)", "1111001a1-000bcd----10x10-01efgh") // ASIMD
//INST(asimd_VMOV_imm, "VMOV (immediate)", "1111001a1-000bcd----11xx0-01efgh") // ASIMD
//INST(asimd_VMVN_imm, "VMVN (immediate)", "1111001a1-000bcd----0xx00-11efgh") // ASIMD
//INST(asimd_VBIC_imm, "VBIC (immediate)", "1111001a1-000bcd----0xx10-11efgh") // ASIMD
//INST(asimd_VMVN_imm, "VMVN (immediate)", "1111001a1-000bcd----10x00-11efgh") // ASIMD
//INST(asimd_VBIC_imm, "VBIC (immediate)", "1111001a1-000bcd----10x10-11efgh") // ASIMD
//INST(asimd_VMVN_imm, "VMVN (immediate)", "1111001a1-000bcd----110x0-11efgh") // ASIMD
//INST(asimd_VMOV_imm, "VMOV (immediate)", "1111001a1-000bcd----11100-11efgh") // ASIMD

View file

@ -1,5 +1,3 @@
// cccc1110________----101-__-0----
// Floating-point three-register data processing instructions
INST(vfp_VMLA, "VMLA", "cccc11100D00nnnndddd101zN0M0mmmm") // VFPv2
INST(vfp_VMLS, "VMLS", "cccc11100D00nnnndddd101zN1M0mmmm") // VFPv2
@ -10,6 +8,27 @@ INST(vfp_VNMUL, "VNMUL", "cccc11100D10nnnndddd101zN
INST(vfp_VADD, "VADD", "cccc11100D11nnnndddd101zN0M0mmmm") // VFPv2
INST(vfp_VSUB, "VSUB", "cccc11100D11nnnndddd101zN1M0mmmm") // VFPv2
INST(vfp_VDIV, "VDIV", "cccc11101D00nnnndddd101zN0M0mmmm") // VFPv2
//INST(vfp_VFNMA, "VFNMA", "cccc11101D01nnnndddd101zN0M0mmmm") // VFPv4
//INST(vfp_VFNMS, "VFNMS", "cccc11101D01nnnndddd101zN1M0mmmm") // VFPv4
//INST(vfp_VFMA, "VFMA", "cccc11101D10nnnndddd101zN0M0mmmm") // VFPv4
//INST(vfp_VFMS, "VFMS", "cccc11101D10nnnndddd101zN1M0mmmm") // VFPv4
// 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", "cccc11101D11001odddd1010T1M0mmmm") // VFPv3HP
//INST(vfp_VCVTT, "VCVTT", "cccc11101D11001odddd1010T1M0mmmm") // VFPv3HP
INST(vfp_VCMP, "VCMP", "cccc11101D110100dddd101zE1M0mmmm") // VFPv2
INST(vfp_VCMP_zero, "VCMP (with zero)", "cccc11101D110101dddd101zE1000000") // VFPv2
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
// Floating-point move instructions
INST(vfp_VMOV_u32_f64, "VMOV (core to f64)", "cccc11100000ddddtttt1011D0010000") // VFPv2
@ -20,18 +39,6 @@ INST(vfp_VMOV_2u32_2f32, "VMOV (2xcore to 2xf32)", "cccc11000100uuuutttt10100
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_reg, "VMOV (reg)", "cccc11101D110000dddd101z01M0mmmm") // VFPv2
// Floating-point other instructions
INST(vfp_VABS, "VABS", "cccc11101D110000dddd101z11M0mmmm") // VFPv2
INST(vfp_VNEG, "VNEG", "cccc11101D110001dddd101z01M0mmmm") // VFPv2
INST(vfp_VSQRT, "VSQRT", "cccc11101D110001dddd101z11M0mmmm") // VFPv2
INST(vfp_VCVT_f_to_f, "VCVT (f32<->f64)", "cccc11101D110111dddd101z11M0mmmm") // VFPv2
INST(vfp_VCVT_to_float, "VCVT (to float)", "cccc11101D111000dddd101zs1M0mmmm") // VFPv2
INST(vfp_VCVT_to_u32, "VCVT (to u32)", "cccc11101D111100dddd101zr1M0mmmm") // VFPv2
INST(vfp_VCVT_to_s32, "VCVT (to s32)", "cccc11101D111101dddd101zr1M0mmmm") // VFPv2
INST(vfp_VCMP, "VCMP", "cccc11101D110100dddd101zE1M0mmmm") // VFPv2
INST(vfp_VCMP_zero, "VCMP (with zero)", "cccc11101D110101dddd101zE1000000") // VFPv2
// Floating-point system register access
INST(vfp_VMSR, "VMSR", "cccc111011100001tttt101000010000") // VFPv2

View file

@ -1268,7 +1268,7 @@ public:
return fmt::format("vcvt{}.{}.{} {}, {}", CondToString(cond), !sz ? "f64" : "f32", sz ? "f64" : "f32", FPRegStr(!sz, Vd, D), FPRegStr(sz, Vm, M));
}
std::string vfp_VCVT_to_float(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm) {
std::string vfp_VCVT_from_int(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm) {
return fmt::format("vcvt{}.{}.{} {}, {}", CondToString(cond), sz ? "f64" : "f32", is_signed ? "s32" : "u32", FPRegStr(sz, Vd, D), FPRegStr(false, Vm, M));
}

View file

@ -388,7 +388,7 @@ struct ArmTranslatorVisitor final {
bool vfp_VNEG(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
bool vfp_VSQRT(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
bool vfp_VCVT_f_to_f(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
bool vfp_VCVT_to_float(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm);
bool vfp_VCVT_from_int(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm);
bool vfp_VCVT_to_u32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm);
bool vfp_VCVT_to_s32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm);
bool vfp_VCMP(Cond cond, bool D, size_t Vd, bool sz, bool E, bool M, size_t Vm);

View file

@ -493,7 +493,7 @@ bool ArmTranslatorVisitor::vfp_VCVT_f_to_f(Cond cond, bool D, size_t Vd, bool sz
// VCVT.F32.{S32,U32} <Sd>, <Sm>
// VCVT.F64.{S32,U32} <Sd>, <Dm>
bool ArmTranslatorVisitor::vfp_VCVT_to_float(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm) {
bool ArmTranslatorVisitor::vfp_VCVT_from_int(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm) {
if (!ConditionPassed(cond)) {
return true;
}