Bus: Handle CPU-internal narrow writes

The full 32-bits of the GPR are used.

Fixes SoundScope in the BIOS Shell.
This commit is contained in:
Connor McLaughlin 2021-04-26 21:57:00 +10:00
parent 7fb5d6908f
commit 40731b49fc
10 changed files with 102 additions and 124 deletions

View file

@ -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<MemoryAccessType::Write, MemoryAccessSize::Byte>(addr, temp);
const TickCount cycles = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Byte>(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<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(addr))
return false;
u32 temp = ZeroExtend32(value);
const TickCount cycles = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(addr, temp);
const TickCount cycles = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(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<MemoryAccessType::Write, MemoryAccessSize::Byte>(address, temp);
const TickCount cycles = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Byte>(address, value);
if (cycles < 0)
return static_cast<u32>(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<u32>(Exception::AdES);
}
u32 temp = ZeroExtend32(value);
const TickCount cycles = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(address, temp);
const TickCount cycles = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(address, value);
if (cycles < 0)
return static_cast<u32>(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<MemoryAccessType::Write, MemoryAccessSize::Byte>(address, temp);
g_state.pending_ticks += DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Byte>(address, value);
}
void UncheckedWriteMemoryHalfWord(u32 address, u16 value)
void UncheckedWriteMemoryHalfWord(u32 address, u32 value)
{
u32 temp = ZeroExtend32(value);
g_state.pending_ticks += DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(address, temp);
g_state.pending_ticks += DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(address, value);
}
void UncheckedWriteMemoryWord(u32 address, u32 value)

View file

@ -1258,11 +1258,11 @@ restart_instruction:
if constexpr (debug)
Cop0DataBreakpointCheck<MemoryAccessType::Write>(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<MemoryAccessType::Write>(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;

View file

@ -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);

View file

@ -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);

View file

@ -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.

View file

@ -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);

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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