From 40731b49fc2ef1a7e300d681a03988dedac7e0cc Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Mon, 26 Apr 2021 21:57:00 +1000 Subject: [PATCH] Bus: Handle CPU-internal narrow writes The full 32-bits of the GPR are used. Fixes SoundScope in the BIOS Shell. --- src/core/bus.cpp | 127 +++++++----------- src/core/cpu_core.cpp | 8 +- src/core/cpu_core_private.h | 4 +- src/core/cpu_recompiler_code_generator.cpp | 10 +- src/core/cpu_recompiler_code_generator.h | 9 +- .../cpu_recompiler_code_generator_aarch32.cpp | 12 +- .../cpu_recompiler_code_generator_aarch64.cpp | 14 +- .../cpu_recompiler_code_generator_generic.cpp | 6 +- .../cpu_recompiler_code_generator_x64.cpp | 28 ++-- src/core/cpu_recompiler_thunks.h | 8 +- 10 files changed, 102 insertions(+), 124 deletions(-) diff --git a/src/core/bus.cpp b/src/core/bus.cpp index 88dd3396a..4b852ae82 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -111,20 +111,17 @@ static void ReleaseMemory(); static void SetCodePageFastmemProtection(u32 page_index, bool writable); -#define FIXUP_WORD_READ_OFFSET(offset) ((offset) & ~u32(3)) -#define FIXUP_WORD_READ_VALUE(offset, value) ((value) >> (((offset)&u32(3)) * 8u)) -#define FIXUP_HALFWORD_READ_OFFSET(offset) ((offset) & ~u32(1)) -#define FIXUP_HALFWORD_READ_VALUE(offset, value) ((value) >> (((offset)&u32(1)) * 8u)) -#define FIXUP_HALFWORD_WRITE_VALUE(offset, value) ((value) << (((offset)&u32(1)) * 8u)) +#define FIXUP_HALFWORD_OFFSET(size, offset) ((size >= MemoryAccessSize::HalfWord) ? (offset) : ((offset) & ~1u)) +#define FIXUP_HALFWORD_READ_VALUE(size, offset, value) \ + ((size >= MemoryAccessSize::HalfWord) ? (value) : ((value) >> (((offset)&u32(1)) * 8u))) +#define FIXUP_HALFWORD_WRITE_VALUE(size, offset, value) \ + ((size >= MemoryAccessSize::HalfWord) ? (value) : ((value) << (((offset)&u32(1)) * 8u))) -// Offset and value remapping for (w32) registers from nocash docs. -// TODO: Make template function based on type, and noop for word access -ALWAYS_INLINE static void FixupUnalignedWordAccessW32(u32& offset, u32& value) -{ - const u32 byte_offset = offset & u32(3); - offset &= ~u32(3); - value <<= byte_offset * 8; -} +#define FIXUP_WORD_OFFSET(size, offset) ((size == MemoryAccessSize::Word) ? (offset) : ((offset) & ~3u)) +#define FIXUP_WORD_READ_VALUE(size, offset, value) \ + ((size == MemoryAccessSize::Word) ? (value) : ((value) >> (((offset)&3u) * 8))) +#define FIXUP_WORD_WRITE_VALUE(size, offset, value) \ + ((size == MemoryAccessSize::Word) ? (value) : ((value) << (((offset)&3u) * 8))) bool Initialize() { @@ -971,15 +968,15 @@ ALWAYS_INLINE static TickCount DoMemoryControlAccess(u32 offset, u32& value) { if constexpr (type == MemoryAccessType::Read) { - value = m_MEMCTRL.regs[offset / 4]; - FixupUnalignedWordAccessW32(offset, value); + value = m_MEMCTRL.regs[FIXUP_WORD_OFFSET(size, offset) / 4]; + value = FIXUP_WORD_READ_VALUE(size, offset, value); return 2; } else { - FixupUnalignedWordAccessW32(offset, value); + const u32 index = FIXUP_WORD_OFFSET(size, offset) / 4; + value = FIXUP_WORD_WRITE_VALUE(size, offset, value); - const u32 index = offset / 4; const u32 write_mask = (index == 8) ? COMDELAY::WRITE_MASK : MEMDELAY::WRITE_MASK; const u32 new_value = (m_MEMCTRL.regs[index] & ~write_mask) | (value & write_mask); if (m_MEMCTRL.regs[index] != new_value) @@ -1027,12 +1024,13 @@ ALWAYS_INLINE static TickCount DoPadAccess(u32 offset, u32& value) { if constexpr (type == MemoryAccessType::Read) { - value = g_pad.ReadRegister(offset); + value = g_pad.ReadRegister(FIXUP_HALFWORD_OFFSET(size, offset)); + value = FIXUP_HALFWORD_READ_VALUE(size, offset, value); return 2; } else { - g_pad.WriteRegister(offset, value); + g_pad.WriteRegister(FIXUP_HALFWORD_OFFSET(size, offset), FIXUP_HALFWORD_WRITE_VALUE(size, offset, value)); return 0; } } @@ -1042,12 +1040,13 @@ ALWAYS_INLINE static TickCount DoSIOAccess(u32 offset, u32& value) { if constexpr (type == MemoryAccessType::Read) { - value = g_sio.ReadRegister(offset); + value = g_sio.ReadRegister(FIXUP_HALFWORD_OFFSET(size, offset)); + value = FIXUP_HALFWORD_READ_VALUE(size, offset, value); return 2; } else { - g_sio.WriteRegister(offset, value); + g_sio.WriteRegister(FIXUP_HALFWORD_OFFSET(size, offset), FIXUP_HALFWORD_WRITE_VALUE(size, offset, value)); return 0; } } @@ -1117,14 +1116,13 @@ ALWAYS_INLINE static TickCount DoGPUAccess(u32 offset, u32& value) { if constexpr (type == MemoryAccessType::Read) { - value = g_gpu->ReadRegister(offset); - FixupUnalignedWordAccessW32(offset, value); + value = g_gpu->ReadRegister(FIXUP_WORD_OFFSET(size, offset)); + value = FIXUP_WORD_READ_VALUE(size, offset, value); return 2; } else { - FixupUnalignedWordAccessW32(offset, value); - g_gpu->WriteRegister(offset, value); + g_gpu->WriteRegister(FIXUP_WORD_OFFSET(size, offset), FIXUP_WORD_WRITE_VALUE(size, offset, value)); return 0; } } @@ -1134,14 +1132,13 @@ ALWAYS_INLINE static TickCount DoMDECAccess(u32 offset, u32& value) { if constexpr (type == MemoryAccessType::Read) { - value = g_mdec.ReadRegister(offset); - FixupUnalignedWordAccessW32(offset, value); + value = g_mdec.ReadRegister(FIXUP_WORD_OFFSET(size, offset)); + value = FIXUP_WORD_READ_VALUE(size, offset, value); return 2; } else { - FixupUnalignedWordAccessW32(offset, value); - g_mdec.WriteRegister(offset, value); + g_mdec.WriteRegister(FIXUP_WORD_OFFSET(size, offset), FIXUP_WORD_WRITE_VALUE(size, offset, value)); return 0; } } @@ -1151,14 +1148,13 @@ ALWAYS_INLINE static TickCount DoAccessInterruptController(u32 offset, u32& valu { if constexpr (type == MemoryAccessType::Read) { - value = g_interrupt_controller.ReadRegister(offset); - FixupUnalignedWordAccessW32(offset, value); + value = g_interrupt_controller.ReadRegister(FIXUP_WORD_OFFSET(size, offset)); + value = FIXUP_WORD_READ_VALUE(size, offset, value); return 2; } else { - FixupUnalignedWordAccessW32(offset, value); - g_interrupt_controller.WriteRegister(offset, value); + g_interrupt_controller.WriteRegister(FIXUP_WORD_OFFSET(size, offset), FIXUP_WORD_WRITE_VALUE(size, offset, value)); return 0; } } @@ -1168,14 +1164,13 @@ ALWAYS_INLINE static TickCount DoAccessTimers(u32 offset, u32& value) { if constexpr (type == MemoryAccessType::Read) { - value = g_timers.ReadRegister(offset); - FixupUnalignedWordAccessW32(offset, value); + value = g_timers.ReadRegister(FIXUP_WORD_OFFSET(size, offset)); + value = FIXUP_WORD_READ_VALUE(size, offset, value); return 2; } else { - FixupUnalignedWordAccessW32(offset, value); - g_timers.WriteRegister(offset, value); + g_timers.WriteRegister(FIXUP_WORD_OFFSET(size, offset), FIXUP_WORD_WRITE_VALUE(size, offset, value)); return 0; } } @@ -1205,8 +1200,8 @@ ALWAYS_INLINE static TickCount DoAccessSPU(u32 offset, u32& value) case MemoryAccessSize::Byte: default: { - const u16 value16 = g_spu.ReadRegister(FIXUP_HALFWORD_READ_OFFSET(offset)); - value = FIXUP_HALFWORD_READ_VALUE(offset, value16); + const u16 value16 = g_spu.ReadRegister(FIXUP_HALFWORD_OFFSET(size, offset)); + value = FIXUP_HALFWORD_READ_VALUE(size, offset, value16); } break; } @@ -1236,7 +1231,8 @@ ALWAYS_INLINE static TickCount DoAccessSPU(u32 offset, u32& value) case MemoryAccessSize::Byte: { - g_spu.WriteRegister(FIXUP_HALFWORD_READ_OFFSET(offset), Truncate16(FIXUP_HALFWORD_READ_VALUE(offset, value))); + g_spu.WriteRegister(FIXUP_HALFWORD_OFFSET(size, offset), + Truncate16(FIXUP_HALFWORD_READ_VALUE(size, offset, value))); break; } } @@ -1250,28 +1246,13 @@ ALWAYS_INLINE static TickCount DoDMAAccess(u32 offset, u32& value) { if constexpr (type == MemoryAccessType::Read) { - value = FIXUP_WORD_READ_VALUE(offset, g_dma.ReadRegister(FIXUP_WORD_READ_OFFSET(offset))); + value = g_dma.ReadRegister(FIXUP_WORD_OFFSET(size, offset)); + value = FIXUP_WORD_READ_VALUE(size, offset, value); return 2; } else { - switch (size) - { - case MemoryAccessSize::Byte: - case MemoryAccessSize::HalfWord: - { - // zero extend length register - if ((offset & u32(0xF0)) < 7 && (offset & u32(0x0F)) == 0x4) - value = ZeroExtend32(value); - else - FixupUnalignedWordAccessW32(offset, value); - } - - default: - break; - } - - g_dma.WriteRegister(offset, value); + g_dma.WriteRegister(FIXUP_WORD_OFFSET(size, offset), FIXUP_WORD_WRITE_VALUE(size, offset, value)); return 0; } } @@ -1782,10 +1763,9 @@ bool ReadMemoryWord(VirtualMemoryAddress addr, u32* value) return true; } -bool WriteMemoryByte(VirtualMemoryAddress addr, u8 value) +bool WriteMemoryByte(VirtualMemoryAddress addr, u32 value) { - u32 temp = ZeroExtend32(value); - const TickCount cycles = DoMemoryAccess(addr, temp); + const TickCount cycles = DoMemoryAccess(addr, value); if (cycles < 0) { RaiseException(Exception::DBE); @@ -1796,13 +1776,12 @@ bool WriteMemoryByte(VirtualMemoryAddress addr, u8 value) return true; } -bool WriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value) +bool WriteMemoryHalfWord(VirtualMemoryAddress addr, u32 value) { if (!DoAlignmentCheck(addr)) return false; - u32 temp = ZeroExtend32(value); - const TickCount cycles = DoMemoryAccess(addr, temp); + const TickCount cycles = DoMemoryAccess(addr, value); if (cycles < 0) { RaiseException(Exception::DBE); @@ -1972,10 +1951,9 @@ u64 ReadMemoryWord(u32 address) return ZeroExtend64(temp); } -u32 WriteMemoryByte(u32 address, u8 value) +u32 WriteMemoryByte(u32 address, u32 value) { - u32 temp = ZeroExtend32(value); - const TickCount cycles = DoMemoryAccess(address, temp); + const TickCount cycles = DoMemoryAccess(address, value); if (cycles < 0) return static_cast(Exception::DBE); @@ -1983,7 +1961,7 @@ u32 WriteMemoryByte(u32 address, u8 value) return 0; } -u32 WriteMemoryHalfWord(u32 address, u16 value) +u32 WriteMemoryHalfWord(u32 address, u32 value) { if (!Common::IsAlignedPow2(address, 2)) { @@ -1991,8 +1969,7 @@ u32 WriteMemoryHalfWord(u32 address, u16 value) return static_cast(Exception::AdES); } - u32 temp = ZeroExtend32(value); - const TickCount cycles = DoMemoryAccess(address, temp); + const TickCount cycles = DoMemoryAccess(address, value); if (cycles < 0) return static_cast(Exception::DBE); @@ -2037,16 +2014,14 @@ u32 UncheckedReadMemoryWord(u32 address) return temp; } -void UncheckedWriteMemoryByte(u32 address, u8 value) +void UncheckedWriteMemoryByte(u32 address, u32 value) { - u32 temp = ZeroExtend32(value); - g_state.pending_ticks += DoMemoryAccess(address, temp); + g_state.pending_ticks += DoMemoryAccess(address, value); } -void UncheckedWriteMemoryHalfWord(u32 address, u16 value) +void UncheckedWriteMemoryHalfWord(u32 address, u32 value) { - u32 temp = ZeroExtend32(value); - g_state.pending_ticks += DoMemoryAccess(address, temp); + g_state.pending_ticks += DoMemoryAccess(address, value); } void UncheckedWriteMemoryWord(u32 address, u32 value) diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index b10698cdc..612866a93 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -1258,11 +1258,11 @@ restart_instruction: if constexpr (debug) Cop0DataBreakpointCheck(addr); - const u8 value = Truncate8(ReadReg(inst.i.rt)); + const u32 value = ReadReg(inst.i.rt); WriteMemoryByte(addr, value); if constexpr (pgxp_mode >= PGXPMode::Memory) - PGXP::CPU_SB(inst.bits, value, addr); + PGXP::CPU_SB(inst.bits, Truncate8(value), addr); } break; @@ -1272,11 +1272,11 @@ restart_instruction: if constexpr (debug) Cop0DataBreakpointCheck(addr); - const u16 value = Truncate16(ReadReg(inst.i.rt)); + const u32 value = ReadReg(inst.i.rt); WriteMemoryHalfWord(addr, value); if constexpr (pgxp_mode >= PGXPMode::Memory) - PGXP::CPU_SH(inst.bits, value, addr); + PGXP::CPU_SH(inst.bits, Truncate16(value), addr); } break; diff --git a/src/core/cpu_core_private.h b/src/core/cpu_core_private.h index 9a8a442bf..c2492ca8e 100644 --- a/src/core/cpu_core_private.h +++ b/src/core/cpu_core_private.h @@ -104,8 +104,8 @@ bool SafeReadInstruction(VirtualMemoryAddress addr, u32* value); bool ReadMemoryByte(VirtualMemoryAddress addr, u8* value); bool ReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value); bool ReadMemoryWord(VirtualMemoryAddress addr, u32* value); -bool WriteMemoryByte(VirtualMemoryAddress addr, u8 value); -bool WriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value); +bool WriteMemoryByte(VirtualMemoryAddress addr, u32 value); +bool WriteMemoryHalfWord(VirtualMemoryAddress addr, u32 value); bool WriteMemoryWord(VirtualMemoryAddress addr, u32 value); void* GetDirectReadMemoryPointer(VirtualMemoryAddress address, MemoryAccessSize size, TickCount* read_ticks); void* GetDirectWriteMemoryPointer(VirtualMemoryAddress address, MemoryAccessSize size); diff --git a/src/core/cpu_recompiler_code_generator.cpp b/src/core/cpu_recompiler_code_generator.cpp index 8b8474ff9..7a7900ecf 100644 --- a/src/core/cpu_recompiler_code_generator.cpp +++ b/src/core/cpu_recompiler_code_generator.cpp @@ -1479,7 +1479,7 @@ bool CodeGenerator::Compile_Store(const CodeBlockInstruction& cbi) value.ViewAsSize(RegSize_8), address); } - EmitStoreGuestMemory(cbi, address, address_spec, value.ViewAsSize(RegSize_8)); + EmitStoreGuestMemory(cbi, address, address_spec, RegSize_8, value); if (address_spec) { @@ -1510,7 +1510,7 @@ bool CodeGenerator::Compile_Store(const CodeBlockInstruction& cbi) value.ViewAsSize(RegSize_16), address); } - EmitStoreGuestMemory(cbi, address, address_spec, value.ViewAsSize(RegSize_16)); + EmitStoreGuestMemory(cbi, address, address_spec, RegSize_16, value); if (address_spec) { @@ -1538,7 +1538,7 @@ bool CodeGenerator::Compile_Store(const CodeBlockInstruction& cbi) if (g_settings.gpu_pgxp_enable) EmitFunctionCall(nullptr, PGXP::CPU_SW, Value::FromConstantU32(cbi.instruction.bits), value, address); - EmitStoreGuestMemory(cbi, address, address_spec, value); + EmitStoreGuestMemory(cbi, address, address_spec, RegSize_32, value); if (address_spec) SpeculativeWriteMemory(*address_spec, value_spec); @@ -1683,7 +1683,7 @@ bool CodeGenerator::Compile_StoreLeftRight(const CodeBlockInstruction& cbi) shift.ReleaseAndClear(); - EmitStoreGuestMemory(cbi, address, address_spec, mem); + EmitStoreGuestMemory(cbi, address, address_spec, RegSize_32, mem); if (g_settings.gpu_pgxp_enable) EmitFunctionCall(nullptr, PGXP::CPU_SW, Value::FromConstantU32(cbi.instruction.bits), mem, address); @@ -2741,7 +2741,7 @@ bool CodeGenerator::Compile_cop2(const CodeBlockInstruction& cbi) else { Value value = DoGTERegisterRead(reg); - EmitStoreGuestMemory(cbi, address, spec_address, value); + EmitStoreGuestMemory(cbi, address, spec_address, RegSize_32, value); if (g_settings.gpu_pgxp_enable) EmitFunctionCall(nullptr, PGXP::CPU_SWC2, Value::FromConstantU32(cbi.instruction.bits), value, address); diff --git a/src/core/cpu_recompiler_code_generator.h b/src/core/cpu_recompiler_code_generator.h index c10ceae74..c7d03a8af 100644 --- a/src/core/cpu_recompiler_code_generator.h +++ b/src/core/cpu_recompiler_code_generator.h @@ -89,10 +89,11 @@ public: void EmitLoadGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, Value& result, bool in_far_code); void EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const Value& address, const SpeculativeValue& address_spec, - const Value& value); - void EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, const Value& value); - void EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, const Value& value, - bool in_far_code); + RegSize size, const Value& value); + void EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, + const Value& value); + void EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, + const Value& value, bool in_far_code); void EmitUpdateFastmemBase(); // Unconditional branch to pointer. May allocate a scratch register. diff --git a/src/core/cpu_recompiler_code_generator_aarch32.cpp b/src/core/cpu_recompiler_code_generator_aarch32.cpp index d37e84ae2..a5ef8ffca 100644 --- a/src/core/cpu_recompiler_code_generator_aarch32.cpp +++ b/src/core/cpu_recompiler_code_generator_aarch32.cpp @@ -1376,7 +1376,7 @@ void CodeGenerator::EmitLoadGuestMemorySlowmem(const CodeBlockInstruction& cbi, } } -void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, +void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, const Value& value) { LoadStoreBackpatchInfo bpi; @@ -1408,7 +1408,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, m_register_cache.InhibitAllocation(); bpi.host_pc = GetCurrentNearCodePointer(); - switch (value.size) + switch (size) { case RegSize_8: m_emit->strb(GetHostReg32(actual_value.host_reg), a32::MemOperand(GetHostReg32(RARG1), GetHostReg32(RARG2))); @@ -1435,7 +1435,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, // generate slowmem fallback bpi.host_slowmem_pc = GetCurrentFarCodePointer(); SwitchToFarCode(); - EmitStoreGuestMemorySlowmem(cbi, address, actual_value, true); + EmitStoreGuestMemorySlowmem(cbi, address, size, actual_value, true); // restore fastmem base state for the next instruction if (old_load_fastmem_base) @@ -1451,7 +1451,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, m_block->loadstore_backpatch_info.push_back(bpi); } -void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, +void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, const Value& value, bool in_far_code) { AddPendingCycles(true); @@ -1463,7 +1463,7 @@ void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, Assert(!in_far_code); Value result = m_register_cache.AllocateScratch(RegSize_32); - switch (value.size) + switch (size) { case RegSize_8: EmitFunctionCall(&result, &Thunks::WriteMemoryByte, address, value_in_hr); @@ -1509,7 +1509,7 @@ void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, } else { - switch (value.size) + switch (size) { case RegSize_8: EmitFunctionCall(nullptr, &Thunks::UncheckedWriteMemoryByte, address, value_in_hr); diff --git a/src/core/cpu_recompiler_code_generator_aarch64.cpp b/src/core/cpu_recompiler_code_generator_aarch64.cpp index 04978c80c..3d6e4346f 100644 --- a/src/core/cpu_recompiler_code_generator_aarch64.cpp +++ b/src/core/cpu_recompiler_code_generator_aarch64.cpp @@ -1557,7 +1557,7 @@ void CodeGenerator::EmitLoadGuestMemorySlowmem(const CodeBlockInstruction& cbi, } } -void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, +void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, const Value& value) { Value value_in_hr = GetValueInHostRegister(value); @@ -1584,7 +1584,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, { bpi.host_pc = GetCurrentNearCodePointer(); - switch (value.size) + switch (size) { case RegSize_8: m_emit->strb(GetHostReg8(value_in_hr), a64::MemOperand(GetFastmemBasePtrReg(), GetHostReg32(address_reg))); @@ -1612,7 +1612,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, bpi.host_pc = GetCurrentNearCodePointer(); - switch (value.size) + switch (size) { case RegSize_8: m_emit->strb(GetHostReg32(value_in_hr.host_reg), a64::MemOperand(GetHostReg64(RARG1), GetHostReg32(RARG2))); @@ -1639,7 +1639,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, bpi.host_slowmem_pc = GetCurrentFarCodePointer(); SwitchToFarCode(); - EmitStoreGuestMemorySlowmem(cbi, address, value_in_hr, true); + EmitStoreGuestMemorySlowmem(cbi, address, size, value_in_hr, true); // return to the block code EmitBranch(GetCurrentNearCodePointer(), false); @@ -1650,7 +1650,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, m_block->loadstore_backpatch_info.push_back(bpi); } -void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, +void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, const Value& value, bool in_far_code) { AddPendingCycles(true); @@ -1662,7 +1662,7 @@ void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, Assert(!in_far_code); Value result = m_register_cache.AllocateScratch(RegSize_32); - switch (value.size) + switch (size) { case RegSize_8: EmitFunctionCall(&result, &Thunks::WriteMemoryByte, address, value_in_hr); @@ -1707,7 +1707,7 @@ void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, } else { - switch (value.size) + switch (size) { case RegSize_8: EmitFunctionCall(nullptr, &Thunks::UncheckedWriteMemoryByte, address, value_in_hr); diff --git a/src/core/cpu_recompiler_code_generator_generic.cpp b/src/core/cpu_recompiler_code_generator_generic.cpp index cf34d7e67..270ef118b 100644 --- a/src/core/cpu_recompiler_code_generator_generic.cpp +++ b/src/core/cpu_recompiler_code_generator_generic.cpp @@ -114,7 +114,7 @@ Value CodeGenerator::EmitLoadGuestMemory(const CodeBlockInstruction& cbi, const } void CodeGenerator::EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const Value& address, - const SpeculativeValue& address_spec, const Value& value) + const SpeculativeValue& address_spec, RegSize size, const Value& value) { if (address.IsConstant() && !SpeculativeIsCacheIsolated()) { @@ -149,12 +149,12 @@ void CodeGenerator::EmitStoreGuestMemory(const CodeBlockInstruction& cbi, const if (g_settings.IsUsingFastmem() && use_fastmem) { - EmitStoreGuestMemoryFastmem(cbi, address, value); + EmitStoreGuestMemoryFastmem(cbi, address, size, value); } else { m_register_cache.FlushCallerSavedGuestRegisters(true, true); - EmitStoreGuestMemorySlowmem(cbi, address, value, false); + EmitStoreGuestMemorySlowmem(cbi, address, size, value, false); } } diff --git a/src/core/cpu_recompiler_code_generator_x64.cpp b/src/core/cpu_recompiler_code_generator_x64.cpp index b7ec8dce7..195d2fae4 100644 --- a/src/core/cpu_recompiler_code_generator_x64.cpp +++ b/src/core/cpu_recompiler_code_generator_x64.cpp @@ -2053,7 +2053,7 @@ void CodeGenerator::EmitLoadGuestMemorySlowmem(const CodeBlockInstruction& cbi, } } -void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, +void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, const Value& value) { // fastmem @@ -2078,7 +2078,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, m_register_cache.InhibitAllocation(); - switch (value.size) + switch (size) { case RegSize_8: { @@ -2086,7 +2086,8 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, { if (value.IsConstant()) { - m_emit->mov(m_emit->byte[GetFastmemBasePtrReg() + actual_address->constant_value], value.constant_value); + m_emit->mov(m_emit->byte[GetFastmemBasePtrReg() + actual_address->constant_value], + value.constant_value & 0xFFu); } else { @@ -2099,7 +2100,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, if (value.IsConstant()) { m_emit->mov(m_emit->byte[GetFastmemBasePtrReg() + GetHostReg64(actual_address->host_reg)], - value.constant_value); + value.constant_value & 0xFFu); } else { @@ -2116,7 +2117,8 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, { if (value.IsConstant()) { - m_emit->mov(m_emit->word[GetFastmemBasePtrReg() + actual_address->constant_value], value.constant_value); + m_emit->mov(m_emit->word[GetFastmemBasePtrReg() + actual_address->constant_value], + value.constant_value & 0xFFFFu); } else { @@ -2129,7 +2131,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, if (value.IsConstant()) { m_emit->mov(m_emit->word[GetFastmemBasePtrReg() + GetHostReg64(actual_address->host_reg)], - value.constant_value); + value.constant_value & 0xFFFFu); } else { @@ -2184,12 +2186,12 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, m_emit->qword[GetFastmemBasePtrReg() + GetHostReg64(RARG1) * 8 + (Bus::FASTMEM_LUT_NUM_PAGES * 8)]); bpi.host_pc = GetCurrentNearCodePointer(); - switch (value.size) + switch (size) { case RegSize_8: { if (value.IsConstant()) - m_emit->mov(m_emit->byte[GetHostReg64(RARG1) + GetHostReg64(RARG2)], value.constant_value); + m_emit->mov(m_emit->byte[GetHostReg64(RARG1) + GetHostReg64(RARG2)], value.constant_value & 0xFFu); else m_emit->mov(m_emit->byte[GetHostReg64(RARG1) + GetHostReg64(RARG2)], GetHostReg8(value)); } @@ -2198,7 +2200,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, case RegSize_16: { if (value.IsConstant()) - m_emit->mov(m_emit->word[GetHostReg64(RARG1) + GetHostReg64(RARG2)], value.constant_value); + m_emit->mov(m_emit->word[GetHostReg64(RARG1) + GetHostReg64(RARG2)], value.constant_value & 0xFFFFu); else m_emit->mov(m_emit->word[GetHostReg64(RARG1) + GetHostReg64(RARG2)], GetHostReg16(value)); } @@ -2230,7 +2232,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, bpi.host_slowmem_pc = GetCurrentFarCodePointer(); SwitchToFarCode(); - EmitStoreGuestMemorySlowmem(cbi, address, value, true); + EmitStoreGuestMemorySlowmem(cbi, address, size, value, true); // return to the block code m_emit->jmp(GetCurrentNearCodePointer()); @@ -2241,7 +2243,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, m_block->loadstore_backpatch_info.push_back(bpi); } -void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, +void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, const Value& address, RegSize size, const Value& value, bool in_far_code) { if (g_settings.cpu_recompiler_memory_exceptions) @@ -2249,7 +2251,7 @@ void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, Assert(!in_far_code); Value result = m_register_cache.AllocateScratch(RegSize_32); - switch (value.size) + switch (size) { case RegSize_8: EmitFunctionCall(&result, &Thunks::WriteMemoryByte, address, value); @@ -2292,7 +2294,7 @@ void CodeGenerator::EmitStoreGuestMemorySlowmem(const CodeBlockInstruction& cbi, } else { - switch (value.size) + switch (size) { case RegSize_8: EmitFunctionCall(nullptr, &Thunks::UncheckedWriteMemoryByte, address, value); diff --git a/src/core/cpu_recompiler_thunks.h b/src/core/cpu_recompiler_thunks.h index cb4171ac6..1a206e0c3 100644 --- a/src/core/cpu_recompiler_thunks.h +++ b/src/core/cpu_recompiler_thunks.h @@ -20,16 +20,16 @@ void CheckAndUpdateICache(u32 pc, u32 line_count); u64 ReadMemoryByte(u32 address); u64 ReadMemoryHalfWord(u32 address); u64 ReadMemoryWord(u32 address); -u32 WriteMemoryByte(u32 address, u8 value); -u32 WriteMemoryHalfWord(u32 address, u16 value); +u32 WriteMemoryByte(u32 address, u32 value); +u32 WriteMemoryHalfWord(u32 address, u32 value); u32 WriteMemoryWord(u32 address, u32 value); // Unchecked memory access variants. No alignment or bus exceptions. u32 UncheckedReadMemoryByte(u32 address); u32 UncheckedReadMemoryHalfWord(u32 address); u32 UncheckedReadMemoryWord(u32 address); -void UncheckedWriteMemoryByte(u32 address, u8 value); -void UncheckedWriteMemoryHalfWord(u32 address, u16 value); +void UncheckedWriteMemoryByte(u32 address, u32 value); +void UncheckedWriteMemoryHalfWord(u32 address, u32 value); void UncheckedWriteMemoryWord(u32 address, u32 value); } // namespace Recompiler::Thunks