From d1e62b99932a3404a4a9ad641ebcf2711af7eb5b Mon Sep 17 00:00:00 2001 From: MerryMage Date: Mon, 3 May 2021 22:33:37 +0100 Subject: [PATCH] T32: Add VFP instructions --- .../A32/translate/translate_thumb.cpp | 13 ++++++++++ tests/A32/fuzz_arm.cpp | 24 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/frontend/A32/translate/translate_thumb.cpp b/src/frontend/A32/translate/translate_thumb.cpp index 1f2f41b6..9f93c11d 100644 --- a/src/frontend/A32/translate/translate_thumb.cpp +++ b/src/frontend/A32/translate/translate_thumb.cpp @@ -11,6 +11,7 @@ #include "common/bit_util.h" #include "frontend/A32/decoder/thumb16.h" #include "frontend/A32/decoder/thumb32.h" +#include "frontend/A32/decoder/vfp.h" #include "frontend/A32/ir_emitter.h" #include "frontend/A32/location_descriptor.h" #include "frontend/A32/translate/conditional_state.h" @@ -88,6 +89,12 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType m } else { if (const auto decoder = DecodeThumb32(thumb_instruction)) { should_continue = decoder->get().call(visitor, thumb_instruction); + } else if ((thumb_instruction & 0xEC000000) == 0xEC000000) { + if (const auto vfp_decoder = DecodeVFP(thumb_instruction)) { + should_continue = vfp_decoder->get().call(visitor, thumb_instruction); + } else { + should_continue = visitor.thumb32_UDF(); + } } else { should_continue = visitor.thumb32_UDF(); } @@ -134,6 +141,12 @@ bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descri thumb_instruction = Common::SwapHalves32(thumb_instruction); if (const auto decoder = DecodeThumb32(thumb_instruction)) { should_continue = decoder->get().call(visitor, thumb_instruction); + } else if ((thumb_instruction & 0xEC000000) == 0xEC000000) { + if (const auto vfp_decoder = DecodeVFP(thumb_instruction)) { + should_continue = vfp_decoder->get().call(visitor, thumb_instruction); + } else { + should_continue = visitor.thumb32_UDF(); + } } else { should_continue = visitor.thumb32_UDF(); } diff --git a/tests/A32/fuzz_arm.cpp b/tests/A32/fuzz_arm.cpp index 89ec80bc..8dcbf7ed 100644 --- a/tests/A32/fuzz_arm.cpp +++ b/tests/A32/fuzz_arm.cpp @@ -158,6 +158,12 @@ std::vector GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s #undef INST }; + const std::vector> vfp_list { +#define INST(fn, name, bitstring) {#fn, bitstring}, +#include "frontend/A32/decoder/vfp.inc" +#undef INST + }; + std::vector generators; std::vector invalid; @@ -176,6 +182,13 @@ std::vector GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s "thumb32_STREXB", "thumb32_STREXD", "thumb32_STREXH", + + // FPSCR is inaccurate + "vfp_VMRS", + + // Unicorn has incorrect implementation (incorrect rounding and unsets CPSR.T??) + "vfp_VCVT_to_fixed", + "vfp_VCVT_from_fixed", }; for (const auto& [fn, bitstring] : list) { @@ -185,6 +198,17 @@ std::vector GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s } generators.emplace_back(InstructionGenerator{bitstring}); } + for (const auto& [fn, bs] : vfp_list) { + std::string bitstring = bs; + if (bitstring.substr(0, 4) == "cccc" || bitstring.substr(0, 4) == "----") { + bitstring.replace(0, 4, "1110"); + } + if (std::find(do_not_test.begin(), do_not_test.end(), fn) != do_not_test.end()) { + invalid.emplace_back(InstructionGenerator{bitstring.c_str()}); + continue; + } + generators.emplace_back(InstructionGenerator{bitstring.c_str()}); + } return InstructionGeneratorInfo{generators, invalid}; }();