Duckstation/src/pse/cpu_core.h

131 lines
3.9 KiB
C
Raw Normal View History

2019-09-09 07:01:26 +00:00
#pragma once
#include "common/bitfield.h"
#include "cpu_types.h"
#include "types.h"
2019-09-14 03:52:57 +00:00
#include <array>
2019-09-09 07:01:26 +00:00
class StateWrapper;
class Bus;
namespace CPU {
class Core
{
public:
2019-09-14 03:52:57 +00:00
static constexpr VirtualMemoryAddress RESET_VECTOR = UINT32_C(0xBFC00000);
static constexpr PhysicalMemoryAddress DCACHE_LOCATION = UINT32_C(0x1F800000);
static constexpr PhysicalMemoryAddress DCACHE_LOCATION_MASK = UINT32_C(0xFFFFFC00);
static constexpr PhysicalMemoryAddress DCACHE_OFFSET_MASK = UINT32_C(0x000003FF);
static constexpr PhysicalMemoryAddress DCACHE_SIZE = UINT32_C(0x00000400);
2019-09-09 07:01:26 +00:00
Core();
~Core();
bool Initialize(Bus* bus);
void Reset();
bool DoState(StateWrapper& sw);
2019-09-17 04:25:25 +00:00
TickCount Execute();
const Registers& GetRegs() const { return m_regs; }
Registers& GetRegs() { return m_regs; }
2019-09-17 06:26:00 +00:00
void SetSliceTicks(TickCount downcount) { m_slice_ticks = (downcount < m_slice_ticks ? downcount : m_slice_ticks); }
// Sets the PC and flushes the pipeline.
void SetPC(u32 new_pc);
bool SafeReadMemoryByte(VirtualMemoryAddress addr, u8* value);
bool SafeReadMemoryHalfWord(VirtualMemoryAddress addr, u16* value);
bool SafeReadMemoryWord(VirtualMemoryAddress addr, u32* value);
bool SafeWriteMemoryByte(VirtualMemoryAddress addr, u8 value);
bool SafeWriteMemoryHalfWord(VirtualMemoryAddress addr, u16 value);
bool SafeWriteMemoryWord(VirtualMemoryAddress addr, u32 value);
2019-09-17 06:26:00 +00:00
// External IRQs
void SetExternalInterrupt(u8 bit);
void ClearExternalInterrupt(u8 bit);
2019-09-09 07:01:26 +00:00
private:
template<MemoryAccessType type, MemoryAccessSize size, bool is_instruction_fetch, bool raise_exceptions>
bool DoMemoryAccess(VirtualMemoryAddress address, u32& value);
2019-09-09 07:01:26 +00:00
template<MemoryAccessType type, MemoryAccessSize size>
bool DoAlignmentCheck(VirtualMemoryAddress address);
2019-09-14 03:52:57 +00:00
template<MemoryAccessType type, MemoryAccessSize size>
void DoScratchpadAccess(PhysicalMemoryAddress address, 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 WriteMemoryWord(VirtualMemoryAddress addr, u32 value);
2019-09-09 07:01:26 +00:00
// state helpers
bool InUserMode() const { return m_cop0_regs.sr.KUc; }
bool InKernelMode() const { return !m_cop0_regs.sr.KUc; }
void DisassembleAndPrint(u32 addr);
// Fetches the instruction at m_regs.npc
bool FetchInstruction();
void ExecuteInstruction(Instruction inst);
void ExecuteCop0Instruction(Instruction inst);
2019-09-09 07:01:26 +00:00
void Branch(u32 target);
// exceptions
u32 GetExceptionVector(Exception excode) const;
void RaiseException(Exception excode, u8 coprocessor = 0);
2019-09-17 06:26:00 +00:00
bool DispatchInterrupts();
2019-09-09 07:01:26 +00:00
// flushes any load delays if present
void FlushLoadDelay();
2019-09-09 07:01:26 +00:00
// clears pipeline of load/branch delays
void FlushPipeline();
// helper functions for registers which aren't writable
u32 ReadReg(Reg rs);
void WriteReg(Reg rd, u32 value);
// helper for generating a load delay write
void WriteRegDelayed(Reg rd, u32 value);
// write to cache control register
void WriteCacheControl(u32 value);
Bus* m_bus = nullptr;
2019-09-17 04:25:25 +00:00
// ticks of master/CPU clock until the next event
TickCount m_slice_ticks = 0;
2019-09-09 07:01:26 +00:00
Registers m_regs = {};
2019-09-17 06:26:00 +00:00
Cop0Registers m_cop0_regs = {};
2019-09-09 07:01:26 +00:00
Instruction m_next_instruction = {};
// address of the instruction currently being executed
u32 m_current_instruction_pc = 0;
2019-09-09 07:01:26 +00:00
// load delays
Reg m_load_delay_reg = Reg::count;
u32 m_load_delay_old_value = 0;
Reg m_next_load_delay_reg = Reg::count;
u32 m_next_load_delay_old_value = 0;
2019-09-17 06:26:00 +00:00
bool m_in_branch_delay_slot = false;
bool m_branched = false;
2019-09-09 07:01:26 +00:00
u32 m_cache_control = 0;
2019-09-14 03:52:57 +00:00
// data cache (used as scratchpad)
std::array<u8, DCACHE_SIZE> m_dcache = {};
2019-09-09 07:01:26 +00:00
};
extern bool TRACE_EXECUTION;
} // namespace CPU
#include "cpu_core.inl"