T32: Add ASIMD instructions
This commit is contained in:
parent
d1e62b9993
commit
a5a210a9a5
2 changed files with 44 additions and 0 deletions
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "common/assert.h"
|
||||
#include "common/bit_util.h"
|
||||
#include "frontend/A32/decoder/asimd.h"
|
||||
#include "frontend/A32/decoder/thumb16.h"
|
||||
#include "frontend/A32/decoder/thumb32.h"
|
||||
#include "frontend/A32/decoder/vfp.h"
|
||||
|
@ -64,6 +65,20 @@ std::tuple<u32, ThumbInstSize> ReadThumbInstruction(u32 arm_pc, MemoryReadCodeFu
|
|||
return std::make_tuple(static_cast<u32>((first_part << 16) | second_part), ThumbInstSize::Thumb32);
|
||||
}
|
||||
|
||||
// Convert from thumb ASIMD format to ARM ASIMD format.
|
||||
u32 ConvertASIMDInstruction(u32 thumb_instruction) {
|
||||
if ((thumb_instruction & 0xEF000000) == 0xEF000000) {
|
||||
const bool U = Common::Bit<28>(thumb_instruction);
|
||||
return 0xF2000000 | (U << 24) | (thumb_instruction & 0x00FFFFFF);
|
||||
}
|
||||
|
||||
if ((thumb_instruction & 0xFF000000) == 0xF9000000) {
|
||||
return 0xF4000000 | (thumb_instruction & 0x00FFFFFF);
|
||||
}
|
||||
|
||||
return 0xF7F0A000; // UDF
|
||||
}
|
||||
|
||||
} // local namespace
|
||||
|
||||
IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, const TranslationOptions& options) {
|
||||
|
@ -92,6 +107,8 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryReadCodeFuncType m
|
|||
} 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 if (const auto asimd_decoder = DecodeASIMD<TranslatorVisitor>(ConvertASIMDInstruction(thumb_instruction))) {
|
||||
should_continue = asimd_decoder->get().call(visitor, ConvertASIMDInstruction(thumb_instruction));
|
||||
} else {
|
||||
should_continue = visitor.thumb32_UDF();
|
||||
}
|
||||
|
@ -144,6 +161,8 @@ bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descri
|
|||
} 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 if (const auto asimd_decoder = DecodeASIMD<TranslatorVisitor>(ConvertASIMDInstruction(thumb_instruction))) {
|
||||
should_continue = asimd_decoder->get().call(visitor, ConvertASIMDInstruction(thumb_instruction));
|
||||
} else {
|
||||
should_continue = visitor.thumb32_UDF();
|
||||
}
|
||||
|
|
|
@ -164,6 +164,12 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
|
|||
#undef INST
|
||||
};
|
||||
|
||||
const std::vector<std::tuple<std::string, const char*>> asimd_list {
|
||||
#define INST(fn, name, bitstring) {#fn, bitstring},
|
||||
#include "frontend/A32/decoder/asimd.inc"
|
||||
#undef INST
|
||||
};
|
||||
|
||||
std::vector<InstructionGenerator> generators;
|
||||
std::vector<InstructionGenerator> invalid;
|
||||
|
||||
|
@ -189,6 +195,8 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
|
|||
// Unicorn has incorrect implementation (incorrect rounding and unsets CPSR.T??)
|
||||
"vfp_VCVT_to_fixed",
|
||||
"vfp_VCVT_from_fixed",
|
||||
"asimd_VRECPS", // Unicorn does not fuse the multiply and subtraction, resulting in being off by 1ULP.
|
||||
"asimd_VRSQRTS", // Unicorn does not fuse the multiply and subtraction, resulting in being off by 1ULP.
|
||||
};
|
||||
|
||||
for (const auto& [fn, bitstring] : list) {
|
||||
|
@ -209,6 +217,23 @@ std::vector<u16> GenRandomThumbInst(u32 pc, bool is_last_inst, A32::ITState it_s
|
|||
}
|
||||
generators.emplace_back(InstructionGenerator{bitstring.c_str()});
|
||||
}
|
||||
for (const auto& [fn, bs] : asimd_list) {
|
||||
std::string bitstring = bs;
|
||||
if (bitstring.substr(0, 7) == "1111001") {
|
||||
const char U = bitstring[7];
|
||||
bitstring.replace(0, 8, "111-1111");
|
||||
bitstring[3] = U;
|
||||
} else if (bitstring.substr(0, 8) == "11110100") {
|
||||
bitstring.replace(0, 8, "11111001");
|
||||
} else {
|
||||
ASSERT_FALSE("Unhandled ASIMD instruction: {} {}", fn, bs);
|
||||
}
|
||||
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};
|
||||
}();
|
||||
|
||||
|
|
Loading…
Reference in a new issue