diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp index b44ac807..ddf557fd 100644 --- a/src/common/x64/cpu_detect.cpp +++ b/src/common/x64/cpu_detect.cpp @@ -82,7 +82,7 @@ static CPUCaps Detect() { caps.vendor = CPUVendor::OTHER; // Set reasonable default brand string even if brand string not available - strcpy_s(caps.cpu_string, caps.brand_string); + strcpy_s(caps.cpu_string, sizeof(caps.cpu_string), caps.brand_string); // Detect family and other miscellaneous features if (max_std_fn >= 1) { diff --git a/src/frontend/decoder/thumb16.h b/src/frontend/decoder/thumb16.h index d59e1d86..9bc9d065 100644 --- a/src/frontend/decoder/thumb16.h +++ b/src/frontend/decoder/thumb16.h @@ -125,7 +125,7 @@ boost::optional&> DecodeThumb16(u16 instruction) { INST(&V::thumb16_UXTH, "UXTH", "1011001010mmmddd"), // v6 INST(&V::thumb16_UXTB, "UXTB", "1011001011mmmddd"), // v6 INST(&V::thumb16_PUSH, "PUSH", "1011010Mxxxxxxxx"), // v4T - //INST(&V::thumb16_POP, "POP", "1011110rxxxxxxxx"), // v4T + INST(&V::thumb16_POP, "POP", "1011110Pxxxxxxxx"), // v4T //INST(&V::thumb16_SETEND, "SETEND", "101101100101x000"), // v6 //INST(&V::thumb16_CPS, "CPS", "10110110011m0aif"), // v6 INST(&V::thumb16_REV, "REV", "1011101000mmmddd"), // v6 diff --git a/src/frontend/disassembler/disassembler_thumb.cpp b/src/frontend/disassembler/disassembler_thumb.cpp index 25ab21f8..235ce780 100644 --- a/src/frontend/disassembler/disassembler_thumb.cpp +++ b/src/frontend/disassembler/disassembler_thumb.cpp @@ -298,6 +298,24 @@ public: return ret; } + std::string thumb16_POP(bool P, RegList reg_list) { + if (P) + reg_list |= 1 << 15; + + std::string ret = "PUSH "; + bool first_reg = true; + for (size_t i = 0; i < 16; i++) { + if (Common::Bit(i, reg_list)) { + if (!first_reg) + ret += ", "; + ret += RegStr(static_cast(i)); + first_reg = false; + } + } + + return ret; + } + std::string thumb16_REV(Reg m, Reg d) { return Common::StringFromFormat("rev %s, %s", RegStr(d), RegStr(m)); } diff --git a/src/frontend/translate/translate_thumb.cpp b/src/frontend/translate/translate_thumb.cpp index 6f1f5993..98bb5fd4 100644 --- a/src/frontend/translate/translate_thumb.cpp +++ b/src/frontend/translate/translate_thumb.cpp @@ -515,11 +515,12 @@ struct ThumbTranslatorVisitor final { } // PUSH // reg_list cannot encode for R15. - u32 num_bytes_to_push = static_cast(4 * Common::BitCount(reg_list)); + const u32 num_bytes_to_push = static_cast(4 * Common::BitCount(reg_list)); const auto final_address = ir.Sub(ir.GetRegister(Reg::SP), ir.Imm32(num_bytes_to_push)); auto address = final_address; for (size_t i = 0; i < 16; i++) { if (Common::Bit(i, reg_list)) { + // TODO: Deal with alignment auto Ri = ir.GetRegister(static_cast(i)); ir.WriteMemory32(address, Ri); address = ir.Add(address, ir.Imm32(4)); @@ -530,6 +531,26 @@ struct ThumbTranslatorVisitor final { return true; } + bool thumb16_POP(bool P, RegList reg_list) { + if (P) reg_list |= 1 << 15; + if (Common::BitCount(reg_list) < 1) { + return UnpredictableInstruction(); + } + // POP + auto address = ir.GetRegister(Reg::SP); + for (size_t i = 0; i < 15; i++) { + if (Common::Bit(i, reg_list)) { + // TODO: Deal with alignment + auto data = ir.ReadMemory32(address); + ir.SetRegister(static_cast(i), data); + address = ir.Add(address, ir.Imm32(4)); + } + } + ir.SetRegister(Reg::SP, address); + // TODO(optimization): Possible location for an RSB push. + return true; + } + bool thumb16_REV(Reg m, Reg d) { // REV , // Rd cannot encode R15. diff --git a/tests/arm/fuzz_arm.cpp b/tests/arm/fuzz_arm.cpp index db61bdb7..d2834eb6 100644 --- a/tests/arm/fuzz_arm.cpp +++ b/tests/arm/fuzz_arm.cpp @@ -391,4 +391,4 @@ TEST_CASE("Fuzz ARM reversal instructions", "[JitX64]") { return reg_instructions[2].Generate(); }); } -} \ No newline at end of file +} diff --git a/tests/arm/fuzz_thumb.cpp b/tests/arm/fuzz_thumb.cpp index 608e6dc2..49d0b3a9 100644 --- a/tests/arm/fuzz_thumb.cpp +++ b/tests/arm/fuzz_thumb.cpp @@ -163,7 +163,6 @@ static bool DoesBehaviorMatch(const ARMul_State& interp, const Dynarmic::Jit& ji && interp_write_records == jit_write_records; } - void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_execute_count, const size_t run_count, const std::function instruction_generator) { // Prepare memory code_mem.fill(0xE7FE); // b +#0 @@ -274,7 +273,8 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") { ThumbInstGen("1001xxxxxxxxxxxx"), // LDR/STR Rd, [SP, #] ThumbInstGen("10110100xxxxxxxx", // PUSH (R = 0) [](u16 inst){ return Dynarmic::Common::Bits<0, 7>(inst) != 0; }), // Empty reg_list is UNPREDICTABLE - ThumbInstGen("10111100xxxxxxxx"), // POP (R = 0) + ThumbInstGen("10111100xxxxxxxx", // POP (R = 0) + [](u16 inst){ return Dynarmic::Common::Bits<0, 7>(inst) != 0; }), // Empty reg_list is UNPREDICTABLE ThumbInstGen("1100xxxxxxxxxxxx"), // STMIA/LDMIA //ThumbInstGen("101101100101x000"), // SETEND }};