#pragma once #include #include namespace n64 { struct alignas(32) ICacheLine { bool valid; u32 data[8]; u32 ptag; }; struct alignas(32) DCacheLine { bool valid, dirty; u8 data[16]; u32 ptag; int index; }; struct Cop0; inline const u32 GetPhysicalAddressPTag(const u32 paddr) { return paddr >> 12; } inline const int GetICacheLineIndex(u64 vaddr) { return (vaddr >> 5) & 0x1FF; } inline const u32 GetICacheLineStart(u64 paddr) { return paddr & ~0x1F; } inline const int GetDCacheLineIndex(u64 vaddr) { return (vaddr >> 4) & 0x1FF; } inline const u32 GetDCacheLineStart(u64 paddr) { return paddr & ~0xF; } struct InstructionCache { std::array lines; void FillLine(u64, u32); void InvalidateIndex(u64 vaddr) { lines[GetICacheLineIndex(vaddr)].valid = false; } void StoreTag(u64, u32, Cop0 &); void LoadTag(u64 vaddr); void WriteBack(u64 vaddr, u32 paddr, u32 ptag); void InvalidateIndex(u64 vaddr, u32 ptag) { int lineIndex = GetICacheLineIndex(vaddr); if (lines[lineIndex].valid && lines[lineIndex].ptag == ptag) lines[lineIndex].valid = false; } private: }; struct DataCache { std::array lines; void StoreTag(u64, u32, Cop0 &); void LoadTag(u64 vaddr); template void WriteBack(u64 vaddr, u32 paddr); template void WriteBack(u64 vaddr, u32 paddr, u32 ptag); void InvalidateIndex(u64 vaddr) { lines[GetDCacheLineIndex(vaddr)].valid = false; } void InvalidateIndex(u64 vaddr, u32 ptag) { int lineIndex = GetDCacheLineIndex(vaddr); if (lines[lineIndex].valid && lines[lineIndex].ptag == ptag) lines[lineIndex].valid = false; } }; } // namespace n64