diff --git a/include/dynarmic/A32/config.h b/include/dynarmic/A32/config.h index 49a569dd..c0bda863 100644 --- a/include/dynarmic/A32/config.h +++ b/include/dynarmic/A32/config.h @@ -36,6 +36,8 @@ enum class Exception { Breakpoint, /// A PLD instruction was executed. PreloadData, + /// A PLDW instruction was executed. + PreloadDataWithIntentToWrite, }; /// These function pointers may be inserted into compiled code. diff --git a/src/frontend/A32/decoder/arm.inc b/src/frontend/A32/decoder/arm.inc index 0935d7ca..3017f97d 100644 --- a/src/frontend/A32/decoder/arm.inc +++ b/src/frontend/A32/decoder/arm.inc @@ -94,7 +94,8 @@ INST(arm_UXTAB16, "UXTAB16", "cccc01101100nnnnddddrr000111mmmm INST(arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm") // v6 // Hint instructions -INST(arm_PLD, "PLD", "111101-1-101----1111------------") // v5E; different on v7 +INST(arm_PLD_imm, "PLD (imm)", "11110101uz01nnnn1111iiiiiiiiiiii") // v5E for PLD; v7 for PLDW +INST(arm_PLD_reg, "PLD (reg)", "11110111uz01nnnn1111iiiiitt0mmmm") // v5E for PLD; v7 for PLDW INST(arm_SEV, "SEV", "----0011001000001111000000000100") // v6K INST(arm_WFE, "WFE", "----0011001000001111000000000010") // v6K INST(arm_WFI, "WFI", "----0011001000001111000000000011") // v6K diff --git a/src/frontend/A32/disassembler/disassembler_arm.cpp b/src/frontend/A32/disassembler/disassembler_arm.cpp index 59d52ac7..4bccdfcb 100644 --- a/src/frontend/A32/disassembler/disassembler_arm.cpp +++ b/src/frontend/A32/disassembler/disassembler_arm.cpp @@ -436,7 +436,18 @@ public: } // Hint instructions - std::string arm_PLD() { return "pld "; } + std::string arm_PLD_imm(bool add, bool R, Reg n, Imm<12> imm12) { + const char sign = add ? '+' : '-'; + const char* const w = R ? "" : "w"; + + return fmt::format("pld{} [{}, #{}{:x}]", w, n, sign, imm12.ZeroExtend()); + } + std::string arm_PLD_reg(bool add, bool R, Reg n, Imm<5> imm5, ShiftType shift, Reg m) { + const char sign = add ? '+' : '-'; + const char* const w = R ? "" : "w"; + + return fmt::format("pld{} [{}, {}{}{}]", w, n, sign, m, ShiftStr(shift, imm5)); + } std::string arm_SEV() { return "sev "; } std::string arm_WFE() { return "wfe "; } std::string arm_WFI() { return "wfi "; } diff --git a/src/frontend/A32/translate/translate_arm/hint.cpp b/src/frontend/A32/translate/translate_arm/hint.cpp index 8d78ed60..8a098359 100644 --- a/src/frontend/A32/translate/translate_arm/hint.cpp +++ b/src/frontend/A32/translate/translate_arm/hint.cpp @@ -9,8 +9,24 @@ namespace Dynarmic::A32 { -bool ArmTranslatorVisitor::arm_PLD() { - return RaiseException(Exception::PreloadData); +bool ArmTranslatorVisitor::arm_PLD_imm([[maybe_unused]] bool add, + bool R, + [[maybe_unused]] Reg n, + [[maybe_unused]] Imm<12> imm12) { + const auto exception = R ? Exception::PreloadData + : Exception::PreloadDataWithIntentToWrite; + return RaiseException(exception); +} + +bool ArmTranslatorVisitor::arm_PLD_reg([[maybe_unused]] bool add, + bool R, + [[maybe_unused]] Reg n, + [[maybe_unused]] Imm<5> imm5, + [[maybe_unused]] ShiftType shift, + [[maybe_unused]] Reg m) { + const auto exception = R ? Exception::PreloadData + : Exception::PreloadDataWithIntentToWrite; + return RaiseException(exception); } bool ArmTranslatorVisitor::arm_SEV() { diff --git a/src/frontend/A32/translate/translate_arm/translate_arm.h b/src/frontend/A32/translate/translate_arm/translate_arm.h index 038c8104..5f941cc1 100644 --- a/src/frontend/A32/translate/translate_arm/translate_arm.h +++ b/src/frontend/A32/translate/translate_arm/translate_arm.h @@ -164,7 +164,8 @@ struct ArmTranslatorVisitor final { bool arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m); // Hint instructions - bool arm_PLD(); + bool arm_PLD_imm(bool add, bool R, Reg n, Imm<12> imm12); + bool arm_PLD_reg(bool add, bool R, Reg n, Imm<5> imm5, ShiftType shift, Reg m); bool arm_SEV(); bool arm_WFE(); bool arm_WFI(); diff --git a/tests/A32/fuzz_arm.cpp b/tests/A32/fuzz_arm.cpp index 9b0d4d3e..41643682 100644 --- a/tests/A32/fuzz_arm.cpp +++ b/tests/A32/fuzz_arm.cpp @@ -98,7 +98,8 @@ u32 GenRandomInst(u32 pc, bool is_last_inst) { "arm_LDM_eret", "arm_LDM_usr", "arm_STM_usr", // Hint instructions - "arm_NOP", "arm_PLD", "arm_SEV", "arm_WFE", "arm_WFI", "arm_YIELD", + "arm_NOP", "arm_PLD_imm", "arm_PLD_reg", "arm_SEV", + "arm_WFE", "arm_WFI", "arm_YIELD", // E, T, J "arm_BLX_reg", "arm_BLX_imm", "arm_BXJ", "arm_SETEND", // Coprocessor