T32: Add VFP instructions

This commit is contained in:
MerryMage 2021-05-03 22:33:37 +01:00
parent cd837c5b37
commit d1e62b9993
2 changed files with 37 additions and 0 deletions

View file

@ -11,6 +11,7 @@
#include "common/bit_util.h" #include "common/bit_util.h"
#include "frontend/A32/decoder/thumb16.h" #include "frontend/A32/decoder/thumb16.h"
#include "frontend/A32/decoder/thumb32.h" #include "frontend/A32/decoder/thumb32.h"
#include "frontend/A32/decoder/vfp.h"
#include "frontend/A32/ir_emitter.h" #include "frontend/A32/ir_emitter.h"
#include "frontend/A32/location_descriptor.h" #include "frontend/A32/location_descriptor.h"
#include "frontend/A32/translate/conditional_state.h" #include "frontend/A32/translate/conditional_state.h"
@ -88,6 +89,12 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType m
} else { } else {
if (const auto decoder = DecodeThumb32<TranslatorVisitor>(thumb_instruction)) { if (const auto decoder = DecodeThumb32<TranslatorVisitor>(thumb_instruction)) {
should_continue = decoder->get().call(visitor, thumb_instruction); should_continue = decoder->get().call(visitor, thumb_instruction);
} else if ((thumb_instruction & 0xEC000000) == 0xEC000000) {
if (const auto vfp_decoder = DecodeVFP<TranslatorVisitor>(thumb_instruction)) {
should_continue = vfp_decoder->get().call(visitor, thumb_instruction);
} else {
should_continue = visitor.thumb32_UDF();
}
} else { } else {
should_continue = visitor.thumb32_UDF(); should_continue = visitor.thumb32_UDF();
} }
@ -134,6 +141,12 @@ bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descri
thumb_instruction = Common::SwapHalves32(thumb_instruction); thumb_instruction = Common::SwapHalves32(thumb_instruction);
if (const auto decoder = DecodeThumb32<TranslatorVisitor>(thumb_instruction)) { if (const auto decoder = DecodeThumb32<TranslatorVisitor>(thumb_instruction)) {
should_continue = decoder->get().call(visitor, thumb_instruction); should_continue = decoder->get().call(visitor, thumb_instruction);
} else if ((thumb_instruction & 0xEC000000) == 0xEC000000) {
if (const auto vfp_decoder = DecodeVFP<TranslatorVisitor>(thumb_instruction)) {
should_continue = vfp_decoder->get().call(visitor, thumb_instruction);
} else {
should_continue = visitor.thumb32_UDF();
}
} else { } else {
should_continue = visitor.thumb32_UDF(); should_continue = visitor.thumb32_UDF();
} }

View file

@ -158,6 +158,12 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
#undef INST #undef INST
}; };
const std::vector<std::tuple<std::string, const char*>> vfp_list {
#define INST(fn, name, bitstring) {#fn, bitstring},
#include "frontend/A32/decoder/vfp.inc"
#undef INST
};
std::vector<InstructionGenerator> generators; std::vector<InstructionGenerator> generators;
std::vector<InstructionGenerator> invalid; std::vector<InstructionGenerator> invalid;
@ -176,6 +182,13 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
"thumb32_STREXB", "thumb32_STREXB",
"thumb32_STREXD", "thumb32_STREXD",
"thumb32_STREXH", "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) { for (const auto& [fn, bitstring] : list) {
@ -185,6 +198,17 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
} }
generators.emplace_back(InstructionGenerator{bitstring}); 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}; return InstructionGeneratorInfo{generators, invalid};
}(); }();