mirror of
https://github.com/shadergz/cosmic-station.git
synced 2024-11-23 06:09:40 +00:00
Cop0
: Fixes the data types used in the cache
This commit is contained in:
parent
e93610d5c3
commit
05e2d5b5ed
@ -5,9 +5,8 @@
|
|||||||
namespace cosmic::ee {
|
namespace cosmic::ee {
|
||||||
// We don't check for a cache miss here
|
// We don't check for a cache miss here
|
||||||
os::vec CtrlCop::readCache(u32 address, CacheMode mode) {
|
os::vec CtrlCop::readCache(u32 address, CacheMode mode) {
|
||||||
u32 tag{getCachePfn(address, mode)};
|
auto tag{getCachePfn(address, mode)};
|
||||||
Ref<CopCacheLine> cache;
|
auto cache{getCache(address, false, mode)};
|
||||||
cache = getCache(address, false, mode);
|
|
||||||
u8 fix{};
|
u8 fix{};
|
||||||
if (cache->tags[0] == tag)
|
if (cache->tags[0] == tag)
|
||||||
fix = 1;
|
fix = 1;
|
||||||
@ -17,7 +16,7 @@ namespace cosmic::ee {
|
|||||||
if (!fix) {
|
if (!fix) {
|
||||||
throw Cop0Err("Address {} isn't cached or doesn't have a valid tag referencing it", address);
|
throw Cop0Err("Address {} isn't cached or doesn't have a valid tag referencing it", address);
|
||||||
}
|
}
|
||||||
const CopCacheLine::CacheWay cont{cache->ec[fix - 1]};
|
const auto cont{cache->ec[fix - 1]};
|
||||||
return cont.vec[address & 3];
|
return cont.vec[address & 3];
|
||||||
}
|
}
|
||||||
void CtrlCop::invIndexed(u32 address) {
|
void CtrlCop::invIndexed(u32 address) {
|
||||||
@ -30,7 +29,7 @@ namespace cosmic::ee {
|
|||||||
}
|
}
|
||||||
bool CtrlCop::isCacheHit(u32 address, u8 lane, CacheMode mode) {
|
bool CtrlCop::isCacheHit(u32 address, u8 lane, CacheMode mode) {
|
||||||
// Each cache line is indexed by virtual address
|
// Each cache line is indexed by virtual address
|
||||||
u16 tag{getCachePfn(address, mode)};
|
auto tag{getCachePfn(address, mode)};
|
||||||
auto highway{getCache(address, false, mode)};
|
auto highway{getCache(address, false, mode)};
|
||||||
|
|
||||||
if (!highway)
|
if (!highway)
|
||||||
@ -43,20 +42,18 @@ namespace cosmic::ee {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
void CtrlCop::loadCacheLine(u32 address, EeMipsCore& core, CacheMode mode) {
|
void CtrlCop::loadCacheLine(u32 address, EeMipsCore& core, CacheMode mode) {
|
||||||
Ref<CopCacheLine> pear{};
|
auto logical{getCachePfn(address, mode)};
|
||||||
u16 logical{getCachePfn(address, mode)};
|
|
||||||
|
|
||||||
pear = getCache(address, true, mode);
|
auto pear{getCache(address, true, mode)};
|
||||||
assignFlushedCache(*pear, logical);
|
assignFlushedCache(*pear, logical);
|
||||||
if (pear->tags[0] != logical && pear->tags[1] != logical) {
|
if (pear->tags[0] != logical && pear->tags[1] != logical) {
|
||||||
throw Cop0Err("No portion of the cache line {} was properly selected! Tags: {}", logical,
|
throw Cop0Err("No portion of the cache line {} was properly selected! Tags: {}",
|
||||||
fmt::join(pear->tags, ","));
|
logical, fmt::join(pear->tags, ","));
|
||||||
}
|
}
|
||||||
auto cacheData{core.mipsRead<os::vec>(address)};
|
auto cacheData{core.mipsRead<os::vec>(address)};
|
||||||
// Due to the LRF algorithm, we will write to the way that was written last (thus keeping
|
// Due to the LRF algorithm, we will write to the way that was written last (thus keeping
|
||||||
// the last data among the ways in the cache, waiting for one more miss)
|
// the last data among the ways in the cache, waiting for one more miss)
|
||||||
u8 way;
|
u8 way{pear->lrf[0] && !pear->lrf[1]};
|
||||||
way = pear->lrf[0] && !pear->lrf[1];
|
|
||||||
if (!way) {
|
if (!way) {
|
||||||
if (!pear->lrf[0] && pear->lrf[1])
|
if (!pear->lrf[0] && pear->lrf[1])
|
||||||
way = 2;
|
way = 2;
|
||||||
@ -90,9 +87,10 @@ namespace cosmic::ee {
|
|||||||
void CtrlCop::assignFlushedCache(CopCacheLine& eec, u32 tag, CacheMode mode) {
|
void CtrlCop::assignFlushedCache(CopCacheLine& eec, u32 tag, CacheMode mode) {
|
||||||
// The EE uses a Least Recently Filled (LRF) algorithm to determine which way to load data into
|
// The EE uses a Least Recently Filled (LRF) algorithm to determine which way to load data into
|
||||||
u32 assign{};
|
u32 assign{};
|
||||||
std::array<u8, 2> mix{};
|
const std::array<u8, 2> mix{
|
||||||
mix[0] = static_cast<u8>(eec.tags[0] & ~validBit);
|
static_cast<u8>(eec.tags[0] & ~validBit),
|
||||||
mix[1] = static_cast<u8>(eec.tags[1] & ~validBit);
|
static_cast<u8>(eec.tags[1] & ~validBit)
|
||||||
|
};
|
||||||
|
|
||||||
if (mix[0] && !mix[1])
|
if (mix[0] && !mix[1])
|
||||||
assign = 0;
|
assign = 0;
|
||||||
@ -121,8 +119,7 @@ namespace cosmic::ee {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ref<CopCacheLine> CtrlCop::getCache(u32 mem, bool write, CacheMode mode) {
|
Ref<CopCacheLine> CtrlCop::getCache(u32 mem, bool write, CacheMode mode) {
|
||||||
std::array<u8*, 2> wb;
|
std::array<Ref<u8>, 2> wb;
|
||||||
std::array<bool, 2> valid;
|
|
||||||
u32 ci;
|
u32 ci;
|
||||||
std::span<CopCacheLine> cc;
|
std::span<CopCacheLine> cc;
|
||||||
if (mode == Instruction) {
|
if (mode == Instruction) {
|
||||||
@ -132,20 +129,25 @@ namespace cosmic::ee {
|
|||||||
ci = (mem >> 6) & 0x3f;
|
ci = (mem >> 6) & 0x3f;
|
||||||
cc = dataCache;
|
cc = dataCache;
|
||||||
}
|
}
|
||||||
wb[0] = virtMap[cc[ci].tags[0] >> 12];
|
wb[0] = Ref(*virtMap[cc[ci].tags[0] >> 12]);
|
||||||
valid[0] = cc[ci].lrf[0];
|
std::array<bool, 2> valid{
|
||||||
valid[1] = cc[ci].lrf[1];
|
cc[ci].lrf[0],
|
||||||
wb[1] = virtMap[cc[ci].tags[1] >> 12];
|
cc[ci].lrf[1]
|
||||||
|
};
|
||||||
|
wb[1] = Ref(*virtMap[cc[ci].tags[1] >> 12]);
|
||||||
|
|
||||||
if (wb[0] == virtMap[mem >> 12] && valid[0])
|
if (*wb[0] == *virtMap[mem >> 12] && valid[0])
|
||||||
return cc[ci];
|
return cc[ci];
|
||||||
if (wb[1] == virtMap[mem >> 12] && valid[1])
|
if (*wb[1] == *virtMap[mem >> 12] && valid[1])
|
||||||
return cc[ci];
|
return cc[ci];
|
||||||
u32 way{((cc[ci].tags[0] >> 6) & 1) ^ ((cc[ci].tags[1] >> 6) & 1)};
|
const u32 way{(
|
||||||
|
(cc[ci].tags[0] >> 6) & 1) ^
|
||||||
|
((cc[ci].tags[1] >> 6) & 1)
|
||||||
|
};
|
||||||
const auto isDirty{static_cast<bool>(cc[ci].tags[way] & dirtyBit)};
|
const auto isDirty{static_cast<bool>(cc[ci].tags[way] & dirtyBit)};
|
||||||
|
|
||||||
if (write && mode == Data && isDirty) {
|
if (write && mode == Data && isDirty) {
|
||||||
auto wrm{wb[way] + (mem & 0xfc0)};
|
u64 wrm{*wb[way] + (mem & 0xfc0)};
|
||||||
BitCast<u64*>(wrm)[0] = cc[ci].ec[way].large[0];
|
BitCast<u64*>(wrm)[0] = cc[ci].ec[way].large[0];
|
||||||
BitCast<u64*>(wrm)[1] = cc[ci].ec[way].large[1];
|
BitCast<u64*>(wrm)[1] = cc[ci].ec[way].large[1];
|
||||||
BitCast<u64*>(wrm)[2] = cc[ci].ec[way].large[2];
|
BitCast<u64*>(wrm)[2] = cc[ci].ec[way].large[2];
|
||||||
@ -155,9 +157,10 @@ namespace cosmic::ee {
|
|||||||
BitCast<u64*>(wrm)[6] = cc[ci].ec[way].large[6];
|
BitCast<u64*>(wrm)[6] = cc[ci].ec[way].large[6];
|
||||||
BitCast<u64*>(wrm)[7] = cc[ci].ec[way].large[7];
|
BitCast<u64*>(wrm)[7] = cc[ci].ec[way].large[7];
|
||||||
}
|
}
|
||||||
if (write)
|
if (write) {
|
||||||
// If we are writing to the cache, the dirty bit must be set
|
// If we are writing to the cache, the dirty bit must be set
|
||||||
cc[ci].tags[way] |= ~dirtyBit;
|
cc[ci].tags[way] |= ~dirtyBit;
|
||||||
|
}
|
||||||
return cc[ci];
|
return cc[ci];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ namespace cosmic::ee {
|
|||||||
|
|
||||||
void EeMipsCore::handleException(u8 el, u32 exceptVec, u8 code) {
|
void EeMipsCore::handleException(u8 el, u32 exceptVec, u8 code) {
|
||||||
cop0.cause.exCode = code & 0xd;
|
cop0.cause.exCode = code & 0xd;
|
||||||
const u8 savePcId{static_cast<u8>(el == 1 ? 14 : 30)};
|
const auto savePcId{static_cast<u8>(el == 1 ? 14 : 30)};
|
||||||
if (isABranch) {
|
if (isABranch) {
|
||||||
cop0.mtc0(savePcId, eePc - 4);
|
cop0.mtc0(savePcId, eePc - 4);
|
||||||
} else {
|
} else {
|
||||||
|
@ -28,11 +28,6 @@ namespace cosmic::ee {
|
|||||||
}
|
}
|
||||||
u32 pcValue{};
|
u32 pcValue{};
|
||||||
};
|
};
|
||||||
struct EeFlowCtrl {
|
|
||||||
i64 cycles[1],
|
|
||||||
runCycles;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ExecutionMode : u8 {
|
enum ExecutionMode : u8 {
|
||||||
// JIT compiler, the fastest option but with various interpretation issues
|
// JIT compiler, the fastest option but with various interpretation issues
|
||||||
JitRe,
|
JitRe,
|
||||||
@ -41,7 +36,7 @@ namespace cosmic::ee {
|
|||||||
CachedInterpreter
|
CachedInterpreter
|
||||||
};
|
};
|
||||||
|
|
||||||
class EeMipsCore : public EeFlowCtrl {
|
class EeMipsCore {
|
||||||
static constexpr u8 countOfGPRs{32};
|
static constexpr u8 countOfGPRs{32};
|
||||||
public:
|
public:
|
||||||
EeMipsCore(std::shared_ptr<mio::MemoryPipe>& pipe);
|
EeMipsCore(std::shared_ptr<mio::MemoryPipe>& pipe);
|
||||||
@ -95,6 +90,9 @@ namespace cosmic::ee {
|
|||||||
}
|
}
|
||||||
bool isABranch{};
|
bool isABranch{};
|
||||||
u32 delaySlot{};
|
u32 delaySlot{};
|
||||||
|
i64 cycles[1],
|
||||||
|
runCycles;
|
||||||
|
|
||||||
ExecutionMode cpuMode{ExecutionMode::CachedInterpreter};
|
ExecutionMode cpuMode{ExecutionMode::CachedInterpreter};
|
||||||
CtrlCop cop0;
|
CtrlCop cop0;
|
||||||
FpuCop cop1;
|
FpuCop cop1;
|
||||||
|
Loading…
Reference in New Issue
Block a user