A32: Detect unpredictable LDM/STM instructions
This commit is contained in:
parent
cd1560c664
commit
668a43f815
5 changed files with 27 additions and 4 deletions
|
@ -12,4 +12,4 @@ mkdir build && cd build
|
||||||
cmake .. -DBoost_INCLUDE_DIRS=${PWD}/../externals/ext-boost -DCMAKE_BUILD_TYPE=Release -DDYNARMIC_USE_LLVM=1 -DDYNARMIC_TESTS_USE_UNICORN=1 -DDYNARMIC_ENABLE_CPU_FEATURE_DETECTION=0 -G Ninja
|
cmake .. -DBoost_INCLUDE_DIRS=${PWD}/../externals/ext-boost -DCMAKE_BUILD_TYPE=Release -DDYNARMIC_USE_LLVM=1 -DDYNARMIC_TESTS_USE_UNICORN=1 -DDYNARMIC_ENABLE_CPU_FEATURE_DETECTION=0 -G Ninja
|
||||||
ninja
|
ninja
|
||||||
|
|
||||||
./tests/dynarmic_tests --durations yes "~A32:*" "~Fuzz Thumb instructions set 1"
|
./tests/dynarmic_tests --durations yes
|
||||||
|
|
|
@ -12,4 +12,4 @@ mkdir build && cd build
|
||||||
cmake .. -DBoost_INCLUDE_DIRS=${PWD}/../externals/ext-boost -DCMAKE_BUILD_TYPE=Release -DDYNARMIC_USE_LLVM=1 -DDYNARMIC_TESTS_USE_UNICORN=1 -G Ninja
|
cmake .. -DBoost_INCLUDE_DIRS=${PWD}/../externals/ext-boost -DCMAKE_BUILD_TYPE=Release -DDYNARMIC_USE_LLVM=1 -DDYNARMIC_TESTS_USE_UNICORN=1 -G Ninja
|
||||||
ninja
|
ninja
|
||||||
|
|
||||||
./tests/dynarmic_tests --durations yes "~A32:*" "~Fuzz Thumb instructions set 1"
|
./tests/dynarmic_tests --durations yes
|
||||||
|
|
|
@ -768,6 +768,9 @@ bool ArmTranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) {
|
||||||
if (n == Reg::PC || Common::BitCount(list) < 1) {
|
if (n == Reg::PC || Common::BitCount(list) < 1) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
if (W && Common::Bit(static_cast<size_t>(n), list)) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -783,6 +786,9 @@ bool ArmTranslatorVisitor::arm_LDMDA(Cond cond, bool W, Reg n, RegList list) {
|
||||||
if (n == Reg::PC || Common::BitCount(list) < 1) {
|
if (n == Reg::PC || Common::BitCount(list) < 1) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
if (W && Common::Bit(static_cast<size_t>(n), list)) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -798,6 +804,9 @@ bool ArmTranslatorVisitor::arm_LDMDB(Cond cond, bool W, Reg n, RegList list) {
|
||||||
if (n == Reg::PC || Common::BitCount(list) < 1) {
|
if (n == Reg::PC || Common::BitCount(list) < 1) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
if (W && Common::Bit(static_cast<size_t>(n), list)) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -813,6 +822,9 @@ bool ArmTranslatorVisitor::arm_LDMIB(Cond cond, bool W, Reg n, RegList list) {
|
||||||
if (n == Reg::PC || Common::BitCount(list) < 1) {
|
if (n == Reg::PC || Common::BitCount(list) < 1) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
|
if (W && Common::Bit(static_cast<size_t>(n), list)) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
if (!ConditionPassed(cond)) {
|
if (!ConditionPassed(cond)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -829,6 +829,13 @@ bool ThumbTranslatorVisitor::thumb16_BKPT([[maybe_unused]] Imm<8> imm8) {
|
||||||
|
|
||||||
// STM <Rn>!, <reg_list>
|
// STM <Rn>!, <reg_list>
|
||||||
bool ThumbTranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) {
|
bool ThumbTranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) {
|
||||||
|
if (Common::BitCount(reg_list) == 0) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
if (Common::Bit(static_cast<size_t>(n), reg_list) && n != static_cast<Reg>(Common::LowestSetBit(reg_list))) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
auto address = ir.GetRegister(n);
|
auto address = ir.GetRegister(n);
|
||||||
for (size_t i = 0; i < 8; i++) {
|
for (size_t i = 0; i < 8; i++) {
|
||||||
if (Common::Bit(i, reg_list)) {
|
if (Common::Bit(i, reg_list)) {
|
||||||
|
@ -842,8 +849,12 @@ bool ThumbTranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STM <Rn>!, <reg_list>
|
// LDM <Rn>!, <reg_list>
|
||||||
bool ThumbTranslatorVisitor::thumb16_LDMIA(Reg n, RegList reg_list) {
|
bool ThumbTranslatorVisitor::thumb16_LDMIA(Reg n, RegList reg_list) {
|
||||||
|
if (Common::BitCount(reg_list) == 0) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
const bool write_back = !Common::Bit(static_cast<size_t>(n), reg_list);
|
const bool write_back = !Common::Bit(static_cast<size_t>(n), reg_list);
|
||||||
auto address = ir.GetRegister(n);
|
auto address = ir.GetRegister(n);
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") {
|
||||||
// Ensure that the architecturally undefined case of
|
// Ensure that the architecturally undefined case of
|
||||||
// the base register being within the list isn't hit.
|
// the base register being within the list isn't hit.
|
||||||
const u32 rn = Dynarmic::Common::Bits<8, 10>(inst);
|
const u32 rn = Dynarmic::Common::Bits<8, 10>(inst);
|
||||||
return (inst & (1U << rn)) == 0;
|
return (inst & (1U << rn)) == 0 && Dynarmic::Common::Bits<0, 7>(inst) != 0;
|
||||||
}),
|
}),
|
||||||
// TODO: We should properly test against swapped
|
// TODO: We should properly test against swapped
|
||||||
// endianness cases, however Unicorn doesn't
|
// endianness cases, however Unicorn doesn't
|
||||||
|
|
Loading…
Reference in a new issue