diff --git a/.travis/sse3-only-on-x86_64-linux/build.sh b/.travis/sse3-only-on-x86_64-linux/build.sh index d647c794..7ca3fd2d 100755 --- a/.travis/sse3-only-on-x86_64-linux/build.sh +++ b/.travis/sse3-only-on-x86_64-linux/build.sh @@ -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 ninja -./tests/dynarmic_tests --durations yes "~A32:*" "~Fuzz Thumb instructions set 1" +./tests/dynarmic_tests --durations yes diff --git a/.travis/test-with-unicorn-on-x86_64-linux/build.sh b/.travis/test-with-unicorn-on-x86_64-linux/build.sh index f0385e8d..05ac2c68 100755 --- a/.travis/test-with-unicorn-on-x86_64-linux/build.sh +++ b/.travis/test-with-unicorn-on-x86_64-linux/build.sh @@ -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 ninja -./tests/dynarmic_tests --durations yes "~A32:*" "~Fuzz Thumb instructions set 1" +./tests/dynarmic_tests --durations yes diff --git a/src/frontend/A32/translate/impl/load_store.cpp b/src/frontend/A32/translate/impl/load_store.cpp index 3d2dfb09..715aa8c0 100644 --- a/src/frontend/A32/translate/impl/load_store.cpp +++ b/src/frontend/A32/translate/impl/load_store.cpp @@ -768,6 +768,9 @@ bool ArmTranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) { if (n == Reg::PC || Common::BitCount(list) < 1) { return UnpredictableInstruction(); } + if (W && Common::Bit(static_cast(n), list)) { + return UnpredictableInstruction(); + } if (!ConditionPassed(cond)) { 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) { return UnpredictableInstruction(); } + if (W && Common::Bit(static_cast(n), list)) { + return UnpredictableInstruction(); + } if (!ConditionPassed(cond)) { 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) { return UnpredictableInstruction(); } + if (W && Common::Bit(static_cast(n), list)) { + return UnpredictableInstruction(); + } if (!ConditionPassed(cond)) { 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) { return UnpredictableInstruction(); } + if (W && Common::Bit(static_cast(n), list)) { + return UnpredictableInstruction(); + } if (!ConditionPassed(cond)) { return true; diff --git a/src/frontend/A32/translate/impl/thumb16.cpp b/src/frontend/A32/translate/impl/thumb16.cpp index bf19e265..c825f872 100644 --- a/src/frontend/A32/translate/impl/thumb16.cpp +++ b/src/frontend/A32/translate/impl/thumb16.cpp @@ -829,6 +829,13 @@ bool ThumbTranslatorVisitor::thumb16_BKPT([[maybe_unused]] Imm<8> imm8) { // STM !, bool ThumbTranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) { + if (Common::BitCount(reg_list) == 0) { + return UnpredictableInstruction(); + } + if (Common::Bit(static_cast(n), reg_list) && n != static_cast(Common::LowestSetBit(reg_list))) { + return UnpredictableInstruction(); + } + auto address = ir.GetRegister(n); for (size_t i = 0; i < 8; i++) { if (Common::Bit(i, reg_list)) { @@ -842,8 +849,12 @@ bool ThumbTranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) { return true; } -// STM !, +// LDM !, 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(n), reg_list); auto address = ir.GetRegister(n); diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index d8900d55..c1416f30 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -234,7 +234,7 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") { // Ensure that the architecturally undefined case of // the base register being within the list isn't hit. 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 // endianness cases, however Unicorn doesn't