Bus: Handle unaligned byte writes to SPU
This commit is contained in:
parent
c8a00c58eb
commit
a693437bc9
|
@ -19,7 +19,10 @@
|
||||||
Log_SetChannel(Bus);
|
Log_SetChannel(Bus);
|
||||||
|
|
||||||
#define FIXUP_WORD_READ_OFFSET(offset) ((offset) & ~u32(3))
|
#define FIXUP_WORD_READ_OFFSET(offset) ((offset) & ~u32(3))
|
||||||
#define FIXUP_WORD_READ_VALUE(offset, value) ((value) >> (((offset)&u32(3)) * 8))
|
#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))
|
||||||
|
|
||||||
// Offset and value remapping for (w32) registers from nocash docs.
|
// Offset and value remapping for (w32) registers from nocash docs.
|
||||||
void FixupUnalignedWordAccessW32(u32& offset, u32& value)
|
void FixupUnalignedWordAccessW32(u32& offset, u32& value)
|
||||||
|
@ -487,16 +490,27 @@ void Bus::DoWriteTimers(MemoryAccessSize size, u32 offset, u32 value)
|
||||||
|
|
||||||
u32 Bus::DoReadSPU(MemoryAccessSize size, u32 offset)
|
u32 Bus::DoReadSPU(MemoryAccessSize size, u32 offset)
|
||||||
{
|
{
|
||||||
// 32-bit reads are read as two 16-bit accesses.
|
switch (size)
|
||||||
if (size == MemoryAccessSize::Word)
|
|
||||||
{
|
{
|
||||||
const u16 lsb = m_spu->ReadRegister(offset);
|
case MemoryAccessSize::Word:
|
||||||
const u16 msb = m_spu->ReadRegister(offset + 2);
|
{
|
||||||
return ZeroExtend32(lsb) | (ZeroExtend32(msb) << 16);
|
// 32-bit reads are read as two 16-bit accesses.
|
||||||
}
|
const u16 lsb = m_spu->ReadRegister(offset);
|
||||||
else
|
const u16 msb = m_spu->ReadRegister(offset + 2);
|
||||||
{
|
return ZeroExtend32(lsb) | (ZeroExtend32(msb) << 16);
|
||||||
return ZeroExtend32(m_spu->ReadRegister(offset));
|
}
|
||||||
|
|
||||||
|
case MemoryAccessSize::HalfWord:
|
||||||
|
{
|
||||||
|
return ZeroExtend32(m_spu->ReadRegister(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
case MemoryAccessSize::Byte:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
u16 value = m_spu->ReadRegister(FIXUP_HALFWORD_READ_OFFSET(offset));
|
||||||
|
return FIXUP_HALFWORD_READ_VALUE(offset, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,16 +518,29 @@ void Bus::DoWriteSPU(MemoryAccessSize size, u32 offset, u32 value)
|
||||||
{
|
{
|
||||||
// 32-bit writes are written as two 16-bit writes.
|
// 32-bit writes are written as two 16-bit writes.
|
||||||
// TODO: Ignore if address is not aligned.
|
// TODO: Ignore if address is not aligned.
|
||||||
if (size == MemoryAccessSize::Word)
|
switch (size)
|
||||||
{
|
{
|
||||||
Assert(Common::IsAlignedPow2(offset, 2));
|
case MemoryAccessSize::Word:
|
||||||
m_spu->WriteRegister(offset, Truncate16(value));
|
{
|
||||||
m_spu->WriteRegister(offset + 2, Truncate16(value >> 16));
|
DebugAssert(Common::IsAlignedPow2(offset, 2));
|
||||||
return;
|
m_spu->WriteRegister(offset, Truncate16(value));
|
||||||
}
|
m_spu->WriteRegister(offset + 2, Truncate16(value >> 16));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Assert(Common::IsAlignedPow2(offset, 2));
|
case MemoryAccessSize::HalfWord:
|
||||||
m_spu->WriteRegister(offset, Truncate16(value));
|
{
|
||||||
|
DebugAssert(Common::IsAlignedPow2(offset, 2));
|
||||||
|
m_spu->WriteRegister(offset, Truncate16(value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MemoryAccessSize::Byte:
|
||||||
|
{
|
||||||
|
m_spu->WriteRegister(FIXUP_HALFWORD_READ_OFFSET(offset), Truncate16(FIXUP_HALFWORD_READ_VALUE(offset, value)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::DoInvalidateCodeCache(u32 page_index)
|
void Bus::DoInvalidateCodeCache(u32 page_index)
|
||||||
|
|
Loading…
Reference in New Issue