Clean up memory access handlers, reduce template specializations

This commit is contained in:
Connor McLaughlin 2019-09-25 00:36:24 +10:00
parent 4aca52cdf4
commit 9359d0778e
7 changed files with 260 additions and 165 deletions

View file

@ -47,53 +47,65 @@ bool Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_co
void Bus::Reset()
{
m_ram.fill(static_cast<u8>(0));
m_MEMCTRL.exp1_base = 0x1F000000;
m_MEMCTRL.exp2_base = 0x1F802000;
m_MEMCTRL.exp1_delay_size = 0x0013243F;
m_MEMCTRL.exp3_delay_size = 0x00003022;
m_MEMCTRL.bios_delay_size = 0x0013243F;
m_MEMCTRL.spu_delay_size = 0x200931E1;
m_MEMCTRL.cdrom_delay_size = 0x00020843;
m_MEMCTRL.exp2_delay_size = 0x00070777;
m_MEMCTRL.common_delay_size = 0x00031125;
m_ram_size_reg = UINT32_C(0x00000B88);
}
bool Bus::DoState(StateWrapper& sw)
{
sw.DoBytes(m_ram.data(), m_ram.size());
sw.DoBytes(m_bios.data(), m_bios.size());
sw.DoArray(m_MEMCTRL.regs, countof(m_MEMCTRL.regs));
sw.Do(&m_ram_size_reg);
sw.Do(&m_tty_line_buffer);
return !sw.HasError();
}
bool Bus::ReadByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8* value)
bool Bus::ReadByte(PhysicalMemoryAddress address, u8* value)
{
u32 temp = 0;
const bool result = DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Byte>(cpu_address, bus_address, temp);
const bool result = DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Byte>(address, temp);
*value = Truncate8(temp);
return result;
}
bool Bus::ReadHalfWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16* value)
bool Bus::ReadHalfWord(PhysicalMemoryAddress address, u16* value)
{
u32 temp = 0;
const bool result =
DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord>(cpu_address, bus_address, temp);
DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord>(address, temp);
*value = Truncate16(temp);
return result;
}
bool Bus::ReadWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32* value)
bool Bus::ReadWord(PhysicalMemoryAddress address, u32* value)
{
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(cpu_address, bus_address, *value);
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(address, *value);
}
bool Bus::WriteByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8 value)
bool Bus::WriteByte(PhysicalMemoryAddress address, u8 value)
{
u32 temp = ZeroExtend32(value);
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Byte>(cpu_address, bus_address, temp);
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Byte>(address, temp);
}
bool Bus::WriteHalfWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16 value)
bool Bus::WriteHalfWord(PhysicalMemoryAddress address, u16 value)
{
u32 temp = ZeroExtend32(value);
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord>(cpu_address, bus_address, temp);
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord>(address, temp);
}
bool Bus::WriteWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32 value)
bool Bus::WriteWord(PhysicalMemoryAddress address, u32 value)
{
return DispatchAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(cpu_address, bus_address, value);
return DispatchAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(address, value);
}
void Bus::PatchBIOS(u32 address, u32 value, u32 mask /*= UINT32_C(0xFFFFFFFF)*/)
@ -154,8 +166,7 @@ bool Bus::LoadBIOS()
return true;
}
bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress cpu_address,
PhysicalMemoryAddress bus_address, u32& value)
bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value)
{
SmallString str;
str.AppendString("Invalid bus ");
@ -171,7 +182,7 @@ bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, Physical
else
str.AppendString("write");
str.AppendFormattedString(" at address 0x%08X (virtual address 0x%08X)", bus_address, cpu_address);
str.AppendFormattedString(" at address 0x%08X", address);
if (type == MemoryAccessType::Write)
str.AppendFormattedString(" (value 0x%08X)", value);
@ -185,7 +196,7 @@ bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, Physical
bool Bus::DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value)
{
if (m_exp1_rom.empty())
return DoInvalidAccess(MemoryAccessType::Read, size, EXP1_BASE | offset, EXP1_BASE | offset, value);
return DoInvalidAccess(MemoryAccessType::Read, size, EXP1_BASE | offset, value);
if (offset == 0x20018)
{
@ -221,7 +232,7 @@ bool Bus::DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value)
bool Bus::DoWriteEXP1(MemoryAccessSize size, u32 offset, u32 value)
{
return DoInvalidAccess(MemoryAccessType::Write, size, EXP1_BASE | offset, EXP1_BASE | offset, value);
return DoInvalidAccess(MemoryAccessType::Write, size, EXP1_BASE | offset, value);
}
bool Bus::DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value)
@ -235,7 +246,7 @@ bool Bus::DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value)
return true;
}
return DoInvalidAccess(MemoryAccessType::Read, size, EXP2_BASE | offset, EXP2_BASE | offset, value);
return DoInvalidAccess(MemoryAccessType::Read, size, EXP2_BASE | offset, value);
}
bool Bus::DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value)
@ -267,7 +278,43 @@ bool Bus::DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value)
return true;
}
return DoInvalidAccess(MemoryAccessType::Write, size, EXP2_BASE | offset, EXP2_BASE | offset, value);
return DoInvalidAccess(MemoryAccessType::Write, size, EXP2_BASE | offset, value);
}
bool Bus::DoReadMemoryControl(MemoryAccessSize size, u32 offset, u32& value)
{
FixupUnalignedWordAccessW32(offset, value);
value = m_MEMCTRL.regs[offset / 4];
return true;
}
bool Bus::DoWriteMemoryControl(MemoryAccessSize size, u32 offset, u32 value)
{
FixupUnalignedWordAccessW32(offset, value);
m_MEMCTRL.regs[offset / 4] = value;
return true;
}
bool Bus::DoReadMemoryControl2(MemoryAccessSize size, u32 offset, u32& value)
{
if (offset == 0x00)
{
value = m_ram_size_reg;
return true;
}
return DoInvalidAccess(MemoryAccessType::Read, size, MEMCTRL2_BASE | offset, value);
}
bool Bus::DoWriteMemoryControl2(MemoryAccessSize size, u32 offset, u32 value)
{
if (offset == 0x00)
{
m_ram_size_reg = value;
return true;
}
return DoInvalidAccess(MemoryAccessType::Write, size, MEMCTRL2_BASE | offset, value);
}
bool Bus::DoReadPad(MemoryAccessSize size, u32 offset, u32& value)

View file

@ -30,52 +30,84 @@ public:
void Reset();
bool DoState(StateWrapper& sw);
bool ReadByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8* value);
bool ReadHalfWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16* value);
bool ReadWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32* value);
bool WriteByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8 value);
bool WriteHalfWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16 value);
bool WriteWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32 value);
bool ReadByte(PhysicalMemoryAddress address, u8* value);
bool ReadHalfWord(PhysicalMemoryAddress address, u16* value);
bool ReadWord(PhysicalMemoryAddress address, u32* value);
bool WriteByte(PhysicalMemoryAddress address, u8 value);
bool WriteHalfWord(PhysicalMemoryAddress address, u16 value);
bool WriteWord(PhysicalMemoryAddress address, u32 value);
template<MemoryAccessType type, MemoryAccessSize size>
bool DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32& value);
bool DispatchAccess(PhysicalMemoryAddress address, u32& value);
void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF));
void SetExpansionROM(std::vector<u8> data);
private:
static constexpr u32 EXP1_BASE = 0x1F000000;
static constexpr u32 EXP1_SIZE = 0x800000;
static constexpr u32 EXP1_MASK = EXP1_SIZE - 1;
static constexpr u32 PAD_BASE = 0x1F801040;
static constexpr u32 PAD_SIZE = 0x10;
static constexpr u32 PAD_MASK = PAD_SIZE - 1;
static constexpr u32 SIO_BASE = 0x1F801050;
static constexpr u32 SIO_SIZE = 0x10;
static constexpr u32 SIO_MASK = SIO_SIZE - 1;
static constexpr u32 INTERRUPT_CONTROLLER_BASE = 0x1F801070;
static constexpr u32 INTERRUPT_CONTROLLER_SIZE = 0x08;
static constexpr u32 INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1;
static constexpr u32 DMA_BASE = 0x1F801080;
static constexpr u32 DMA_SIZE = 0x80;
static constexpr u32 DMA_MASK = DMA_SIZE - 1;
static constexpr u32 TIMERS_BASE = 0x1F801100;
static constexpr u32 TIMERS_SIZE = 0x40;
static constexpr u32 TIMERS_MASK = TIMERS_SIZE - 1;
static constexpr u32 CDROM_BASE = 0x1F801800;
static constexpr u32 CDROM_SIZE = 0x04;
static constexpr u32 CDROM_MASK = CDROM_SIZE - 1;
static constexpr u32 GPU_BASE = 0x1F801810;
static constexpr u32 GPU_SIZE = 0x10;
static constexpr u32 GPU_MASK = GPU_SIZE - 1;
static constexpr u32 SPU_BASE = 0x1F801C00;
static constexpr u32 SPU_SIZE = 0x300;
static constexpr u32 SPU_MASK = 0x3FF;
static constexpr u32 EXP2_BASE = 0x1F802000;
static constexpr u32 EXP2_SIZE = 0x2000;
static constexpr u32 EXP2_MASK = EXP2_SIZE - 1;
static constexpr u32 BIOS_BASE = 0x1FC00000;
static constexpr u32 BIOS_SIZE = 0x80000;
enum : u32
{
EXP1_BASE = 0x1F000000,
EXP1_SIZE = 0x800000,
EXP1_MASK = EXP1_SIZE - 1,
MEMCTRL_BASE = 0x1F801000,
MEMCTRL_SIZE = 0x40,
MEMCTRL_MASK = MEMCTRL_SIZE - 1,
PAD_BASE = 0x1F801040,
PAD_SIZE = 0x10,
PAD_MASK = PAD_SIZE - 1,
SIO_BASE = 0x1F801050,
SIO_SIZE = 0x10,
SIO_MASK = SIO_SIZE - 1,
MEMCTRL2_BASE = 0x1F801060,
MEMCTRL2_SIZE = 0x10,
MEMCTRL2_MASK = MEMCTRL_SIZE - 1,
INTERRUPT_CONTROLLER_BASE = 0x1F801070,
INTERRUPT_CONTROLLER_SIZE = 0x10,
INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1,
DMA_BASE = 0x1F801080,
DMA_SIZE = 0x80,
DMA_MASK = DMA_SIZE - 1,
TIMERS_BASE = 0x1F801100,
TIMERS_SIZE = 0x40,
TIMERS_MASK = TIMERS_SIZE - 1,
CDROM_BASE = 0x1F801800,
CDROM_SIZE = 0x04,
CDROM_MASK = CDROM_SIZE - 1,
GPU_BASE = 0x1F801810,
GPU_SIZE = 0x10,
GPU_MASK = GPU_SIZE - 1,
SPU_BASE = 0x1F801C00,
SPU_SIZE = 0x300,
SPU_MASK = 0x3FF,
EXP2_BASE = 0x1F802000,
EXP2_SIZE = 0x2000,
EXP2_MASK = EXP2_SIZE - 1,
BIOS_BASE = 0x1FC00000,
BIOS_SIZE = 0x80000
};
enum : u32
{
MEMCTRL_REG_COUNT = 9
};
union MEMCTRL
{
u32 regs[MEMCTRL_REG_COUNT];
struct
{
u32 exp1_base;
u32 exp2_base;
u32 exp1_delay_size;
u32 exp3_delay_size;
u32 bios_delay_size;
u32 spu_delay_size;
u32 cdrom_delay_size;
u32 exp2_delay_size;
u32 common_delay_size;
};
};
bool LoadBIOS();
@ -85,8 +117,7 @@ private:
template<MemoryAccessType type, MemoryAccessSize size>
bool DoBIOSAccess(u32 offset, u32& value);
bool DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress cpu_address,
PhysicalMemoryAddress bus_address, u32& value);
bool DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value);
bool DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteEXP1(MemoryAccessSize size, u32 offset, u32 value);
@ -94,6 +125,12 @@ private:
bool DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadMemoryControl(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteMemoryControl(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadMemoryControl2(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteMemoryControl2(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadPad(MemoryAccessSize size, u32 offset, u32& value);
bool DoWritePad(MemoryAccessSize size, u32 offset, u32 value);
@ -131,6 +168,9 @@ private:
std::array<u8, 524288> m_bios{}; // 512K BIOS ROM
std::vector<u8> m_exp1_rom;
MEMCTRL m_MEMCTRL = {};
u32 m_ram_size_reg = 0;
String m_tty_line_buffer;
};

View file

@ -74,117 +74,107 @@ bool Bus::DoBIOSAccess(u32 offset, u32& value)
}
template<MemoryAccessType type, MemoryAccessSize size>
bool Bus::DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32& value)
bool Bus::DispatchAccess(PhysicalMemoryAddress address, u32& value)
{
if (bus_address < 0x800000)
if (address < 0x800000)
{
return DoRAMAccess<type, size>(bus_address, value);
return DoRAMAccess<type, size>(address, value);
}
else if (bus_address < EXP1_BASE)
else if (address < EXP1_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoInvalidAccess(type, size, address, value);
}
else if (bus_address < (EXP1_BASE + EXP1_SIZE))
else if (address < (EXP1_BASE + EXP1_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadEXP1(size, bus_address & EXP1_MASK, value) :
DoWriteEXP1(size, bus_address & EXP1_MASK, value);
return (type == MemoryAccessType::Read) ? DoReadEXP1(size, address & EXP1_MASK, value) :
DoWriteEXP1(size, address & EXP1_MASK, value);
}
else if (bus_address < PAD_BASE)
else if (address < MEMCTRL_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoInvalidAccess(type, size, address, value);
}
else if (bus_address < (PAD_BASE + PAD_SIZE))
else if (address < (MEMCTRL_BASE + MEMCTRL_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadPad(size, bus_address & PAD_MASK, value) :
DoWritePad(size, bus_address & PAD_MASK, value);
return (type == MemoryAccessType::Read) ? DoReadMemoryControl(size, address & PAD_MASK, value) :
DoWriteMemoryControl(size, address & PAD_MASK, value);
}
else if (bus_address < (SIO_BASE + SIO_SIZE))
else if (address < (PAD_BASE + PAD_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadSIO(size, bus_address & SIO_MASK, value) :
DoWriteSIO(size, bus_address & SIO_MASK, value);
return (type == MemoryAccessType::Read) ? DoReadPad(size, address & PAD_MASK, value) :
DoWritePad(size, address & PAD_MASK, value);
}
else if (bus_address < INTERRUPT_CONTROLLER_BASE)
else if (address < (SIO_BASE + SIO_SIZE))
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return (type == MemoryAccessType::Read) ? DoReadSIO(size, address & SIO_MASK, value) :
DoWriteSIO(size, address & SIO_MASK, value);
}
else if (bus_address < (INTERRUPT_CONTROLLER_BASE + INTERRUPT_CONTROLLER_SIZE))
else if (address < (MEMCTRL2_BASE + MEMCTRL2_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadMemoryControl2(size, address & PAD_MASK, value) :
DoWriteMemoryControl2(size, address & PAD_MASK, value);
}
else if (address < (INTERRUPT_CONTROLLER_BASE + INTERRUPT_CONTROLLER_SIZE))
{
return (type == MemoryAccessType::Read) ?
DoReadInterruptController(size, bus_address & INTERRUPT_CONTROLLER_MASK, value) :
DoWriteInterruptController(size, bus_address & INTERRUPT_CONTROLLER_MASK, value);
DoReadInterruptController(size, address & INTERRUPT_CONTROLLER_MASK, value) :
DoWriteInterruptController(size, address & INTERRUPT_CONTROLLER_MASK, value);
}
else if (bus_address < DMA_BASE)
else if (address < (DMA_BASE + DMA_SIZE))
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return (type == MemoryAccessType::Read) ? DoReadDMA(size, address & DMA_MASK, value) :
DoWriteDMA(size, address & DMA_MASK, value);
}
else if (bus_address < (DMA_BASE + DMA_SIZE))
else if (address < (TIMERS_BASE + TIMERS_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadDMA(size, bus_address & DMA_MASK, value) :
DoWriteDMA(size, bus_address & DMA_MASK, value);
return (type == MemoryAccessType::Read) ? DoReadTimers(size, address & TIMERS_MASK, value) :
DoWriteTimers(size, address & TIMERS_MASK, value);
}
else if (bus_address < TIMERS_BASE)
else if (address < CDROM_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoInvalidAccess(type, size, address, value);
}
else if (bus_address < (TIMERS_BASE + TIMERS_SIZE))
else if (address < (CDROM_BASE + GPU_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadTimers(size, bus_address & TIMERS_MASK, value) :
DoWriteTimers(size, bus_address & TIMERS_MASK, value);
return (type == MemoryAccessType::Read) ? DoReadCDROM(size, address & CDROM_MASK, value) :
DoWriteCDROM(size, address & CDROM_MASK, value);
}
else if (bus_address < CDROM_BASE)
else if (address < GPU_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoInvalidAccess(type, size, address, value);
}
else if (bus_address < (CDROM_BASE + GPU_SIZE))
else if (address < (GPU_BASE + GPU_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadCDROM(size, bus_address & CDROM_MASK, value) :
DoWriteCDROM(size, bus_address & CDROM_MASK, value);
return (type == MemoryAccessType::Read) ? DoReadGPU(size, address & GPU_MASK, value) :
DoWriteGPU(size, address & GPU_MASK, value);
}
else if (bus_address < GPU_BASE)
else if (address < SPU_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoInvalidAccess(type, size, address, value);
}
else if (bus_address < (GPU_BASE + GPU_SIZE))
else if (address < (SPU_BASE + SPU_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadGPU(size, bus_address & GPU_MASK, value) :
DoWriteGPU(size, bus_address & GPU_MASK, value);
return (type == MemoryAccessType::Read) ? DoReadSPU(size, address & SPU_MASK, value) :
DoWriteSPU(size, address & SPU_MASK, value);
}
else if (bus_address < SPU_BASE)
else if (address < EXP2_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoInvalidAccess(type, size, address, value);
}
else if (bus_address < (SPU_BASE + SPU_SIZE))
else if (address < (EXP2_BASE + EXP2_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadSPU(size, bus_address & SPU_MASK, value) :
DoWriteSPU(size, bus_address & SPU_MASK, value);
return (type == MemoryAccessType::Read) ? DoReadEXP2(size, address & EXP2_MASK, value) :
DoWriteEXP2(size, address & EXP2_MASK, value);
}
else if (bus_address < EXP2_BASE)
else if (address < BIOS_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoInvalidAccess(type, size, address, value);
}
else if (bus_address < (EXP2_BASE + EXP2_SIZE))
else if (address < (BIOS_BASE + BIOS_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadEXP2(size, bus_address & EXP2_MASK, value) :
DoWriteEXP2(size, bus_address & EXP2_MASK, value);
}
else if (bus_address < BIOS_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
}
else if (bus_address < (BIOS_BASE + BIOS_SIZE))
{
return DoBIOSAccess<type, size>(static_cast<u32>(bus_address - BIOS_BASE), value);
}
else if (bus_address < 0x1FFE0000)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
}
else if (bus_address < 0x1FFE0200) // I/O Ports (Cache Control)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoBIOSAccess<type, size>(static_cast<u32>(address - BIOS_BASE), value);
}
else
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
return DoInvalidAccess(type, size, address, value);
}
}

View file

@ -92,8 +92,11 @@ void Core::SetPC(u32 new_pc)
bool Core::ReadMemoryByte(VirtualMemoryAddress addr, u8* value)
{
u32 temp = 0;
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Byte, false, true>(addr, temp);
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Byte>(addr, temp);
*value = Truncate8(temp);
if (!result)
RaiseException(Exception::DBE);
return result;
}
@ -103,8 +106,11 @@ bool Core::ReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value)
return false;
u32 temp = 0;
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord, false, true>(addr, temp);
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord>(addr, temp);
*value = Truncate16(temp);
if (!result)
RaiseException(Exception::DBE);
return result;
}
@ -113,13 +119,21 @@ bool Core::ReadMemoryWord(VirtualMemoryAddress addr, u32* value)
if (!DoAlignmentCheck<MemoryAccessType::Read, MemoryAccessSize::Word>(addr))
return false;
return DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word, false, true>(addr, *value);
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(addr, *value);
if (!result)
RaiseException(Exception::DBE);
return result;
}
bool Core::WriteMemoryByte(VirtualMemoryAddress addr, u8 value)
{
u32 temp = ZeroExtend32(value);
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Byte, false, true>(addr, temp);
const bool result = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Byte>(addr, temp);
if (!result)
RaiseException(Exception::DBE);
return result;
}
bool Core::WriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value)
@ -128,7 +142,11 @@ bool Core::WriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value)
return false;
u32 temp = ZeroExtend32(value);
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord, false, true>(addr, temp);
const bool result = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(addr, temp);
if (!result)
RaiseException(Exception::DBE);
return result;
}
bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value)
@ -136,13 +154,17 @@ bool Core::WriteMemoryWord(VirtualMemoryAddress addr, u32 value)
if (!DoAlignmentCheck<MemoryAccessType::Write, MemoryAccessSize::Word>(addr))
return false;
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Word, false, true>(addr, value);
const bool result = DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(addr, value);
if (!result)
RaiseException(Exception::DBE);
return result;
}
bool Core::SafeReadMemoryByte(VirtualMemoryAddress addr, u8* value)
{
u32 temp = 0;
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Byte, false, false>(addr, temp);
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Byte>(addr, temp);
*value = Truncate8(temp);
return result;
}
@ -150,31 +172,31 @@ bool Core::SafeReadMemoryByte(VirtualMemoryAddress addr, u8* value)
bool Core::SafeReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value)
{
u32 temp = 0;
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord, false, false>(addr, temp);
const bool result = DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord>(addr, temp);
*value = Truncate16(temp);
return result;
}
bool Core::SafeReadMemoryWord(VirtualMemoryAddress addr, u32* value)
{
return DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word, false, false>(addr, *value);
return DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(addr, *value);
}
bool Core::SafeWriteMemoryByte(VirtualMemoryAddress addr, u8 value)
{
u32 temp = ZeroExtend32(value);
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Byte, false, false>(addr, temp);
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Byte>(addr, temp);
}
bool Core::SafeWriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value)
{
u32 temp = ZeroExtend32(value);
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord, false, false>(addr, temp);
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::HalfWord>(addr, temp);
}
bool Core::SafeWriteMemoryWord(VirtualMemoryAddress addr, u32 value)
{
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Word, false, false>(addr, value);
return DoMemoryAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(addr, value);
}
void Core::Branch(u32 target)
@ -420,8 +442,8 @@ static constexpr bool SubOverflow(u32 old_value, u32 sub_value, u32 new_value)
void Core::DisassembleAndPrint(u32 addr)
{
u32 bits;
DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word, true, false>(addr, bits);
u32 bits = 0;
DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(addr, bits);
PrintInstruction(bits, addr);
}
@ -459,14 +481,17 @@ bool Core::FetchInstruction()
{
m_regs.pc = m_regs.npc;
if (!DoAlignmentCheck<MemoryAccessType::Read, MemoryAccessSize::Word>(
static_cast<VirtualMemoryAddress>(m_regs.npc)) ||
!DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word, true, true>(
static_cast<VirtualMemoryAddress>(m_regs.npc), m_next_instruction.bits))
if (!DoAlignmentCheck<MemoryAccessType::Read, MemoryAccessSize::Word>(static_cast<VirtualMemoryAddress>(m_regs.npc)))
{
// this will call FetchInstruction() again when the pipeline is flushed.
return false;
}
if (!DoMemoryAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(static_cast<VirtualMemoryAddress>(m_regs.npc),
m_next_instruction.bits))
{
RaiseException(Exception::IBE);
return false;
}
m_regs.npc += sizeof(m_next_instruction.bits);
return true;

View file

@ -41,6 +41,7 @@ public:
// Sets the PC and flushes the pipeline.
void SetPC(u32 new_pc);
// Memory reads variants which do not raise exceptions.
bool SafeReadMemoryByte(VirtualMemoryAddress addr, u8* value);
bool SafeReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value);
bool SafeReadMemoryWord(VirtualMemoryAddress addr, u32* value);
@ -53,7 +54,7 @@ public:
void ClearExternalInterrupt(u8 bit);
private:
template<MemoryAccessType type, MemoryAccessSize size, bool is_instruction_fetch, bool raise_exceptions>
template<MemoryAccessType type, MemoryAccessSize size>
bool DoMemoryAccess(VirtualMemoryAddress address, u32& value);
template<MemoryAccessType type, MemoryAccessSize size>

View file

@ -5,7 +5,7 @@
namespace CPU {
template<MemoryAccessType type, MemoryAccessSize size, bool is_instruction_fetch, bool raise_exceptions>
template<MemoryAccessType type, MemoryAccessSize size>
bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
{
switch (address >> 29)
@ -25,7 +25,7 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
return true;
}
if (!m_bus->DispatchAccess<type, size>(address, phys_addr, value))
if (!m_bus->DispatchAccess<type, size>(phys_addr, value))
{
Panic("Bus error");
return false;
@ -39,7 +39,6 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
case 0x03: // KUSEG 1536M-2048M
{
// Above 512mb raises an exception.
RaiseException(is_instruction_fetch ? Exception::IBE : Exception::DBE);
return false;
}
@ -58,7 +57,7 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
return true;
}
if (!m_bus->DispatchAccess<type, size>(address, address & UINT32_C(0x1FFFFFFF), value))
if (!m_bus->DispatchAccess<type, size>(phys_addr, value))
{
Panic("Bus error");
return false;
@ -71,7 +70,7 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
case 0x05: // KSEG1 - physical memory uncached
{
const PhysicalMemoryAddress phys_addr = address & UINT32_C(0x1FFFFFFF);
if (!m_bus->DispatchAccess<type, size>(address, phys_addr, value))
if (!m_bus->DispatchAccess<type, size>(phys_addr, value))
{
Panic("Bus error");
return false;
@ -95,7 +94,6 @@ bool Core::DoMemoryAccess(VirtualMemoryAddress address, u32& value)
}
else
{
RaiseException(is_instruction_fetch ? Exception::IBE : Exception::DBE);
return false;
}
}

View file

@ -234,8 +234,7 @@ void DMA::RunDMA(Channel channel)
words_remaining--;
u32 value = 0;
m_bus->DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(current_address, current_address,
value);
m_bus->DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(current_address, value);
DMAWrite(channel, value, current_address, words_remaining);
current_address = (current_address + increment) & ADDRESS_MASK;
@ -249,8 +248,7 @@ void DMA::RunDMA(Channel channel)
words_remaining--;
u32 value = DMARead(channel, current_address, words_remaining);
m_bus->DispatchAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(current_address, current_address,
value);
m_bus->DispatchAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(current_address, value);
current_address = (current_address + increment) & ADDRESS_MASK;
} while (words_remaining > 0);
@ -269,8 +267,7 @@ void DMA::RunDMA(Channel channel)
for (;;)
{
u32 header;
m_bus->DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(current_address, current_address,
header);
m_bus->DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(current_address, header);
const u32 word_count = header >> 24;
const u32 next_address = header & UINT32_C(0xFFFFFF);
@ -286,8 +283,7 @@ void DMA::RunDMA(Channel channel)
words_remaining--;
u32 memory_value = 0;
m_bus->DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(current_address, current_address,
memory_value);
m_bus->DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(current_address, memory_value);
DMAWrite(channel, memory_value, current_address, words_remaining);
current_address = (current_address + UINT32_C(4)) & ADDRESS_MASK;
} while (words_remaining > 0);
@ -316,8 +312,7 @@ void DMA::RunDMA(Channel channel)
words_remaining--;
u32 value = 0;
m_bus->DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(current_address, current_address,
value);
m_bus->DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(current_address, value);
DMAWrite(channel, value, current_address, words_remaining);
current_address = (current_address + increment) & ADDRESS_MASK;
@ -331,8 +326,7 @@ void DMA::RunDMA(Channel channel)
words_remaining--;
u32 value = DMARead(channel, current_address, words_remaining);
m_bus->DispatchAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(current_address, current_address,
value);
m_bus->DispatchAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(current_address, value);
current_address = (current_address + increment) & ADDRESS_MASK;
} while (words_remaining > 0);