PI fixes and various smaller fixes

This commit is contained in:
SimoneN64
2024-01-04 02:03:52 +01:00
parent b70188fdb1
commit f0fb01d8e7
8 changed files with 63 additions and 56 deletions

View File

@@ -34,9 +34,7 @@ void Scheduler::tick(u64 t, n64::Mem& mem, n64::Registers& regs) {
while(ticks >= events.top().time) {
switch(auto type = events.top().type) {
case SI_DMA:
si.status.dmaBusy = false;
si.DMA(mem, regs);
InterruptRaise(mi, regs, n64::Interrupt::SI);
break;
case PI_DMA_COMPLETE:
InterruptRaise(mi, regs, n64::Interrupt::PI);

View File

@@ -368,7 +368,7 @@ template<> void Mem::Write<u8>(Registers& regs, u32 paddr, u32 val) {
}
} break;
case REGION_CART:
Util::debug("BusWrite<u8> @ {:08X} = {:02X}", paddr, val);
Util::trace("BusWrite<u8> @ {:08X} = {:02X}", paddr, val);
mmio.pi.BusWrite<u8, false>(*this, paddr, val);
break;
case MMIO_REGION:
@@ -417,7 +417,7 @@ template<> void Mem::Write<u16>(Registers& regs, u32 paddr, u32 val) {
}
} break;
case REGION_CART:
Util::debug("BusWrite<u8> @ {:08X} = {:04X}", paddr, val);
Util::trace("BusWrite<u8> @ {:08X} = {:04X}", paddr, val);
mmio.pi.BusWrite<u16, false>(*this, paddr, val);
break;
case MMIO_REGION:
@@ -464,7 +464,7 @@ template<> void Mem::Write<u32>(Registers& regs, u32 paddr, u32 val) {
}
} break;
case REGION_CART:
Util::debug("BusWrite<u8> @ {:08X} = {:08X}", paddr, val);
Util::trace("BusWrite<u8> @ {:08X} = {:08X}", paddr, val);
mmio.pi.BusWrite<u32, false>(*this, paddr, val);
break;
case MMIO_REGION:
@@ -508,8 +508,8 @@ void Mem::Write(Registers& regs, u32 paddr, u64 val) {
}
} break;
case REGION_CART:
Util::debug("BusWrite<u8> @ {:08X} = {:016X}", paddr, val);
mmio.pi.BusWrite<u64, false>(*this, paddr, val);
Util::trace("BusWrite<u8> @ {:08X} = {:016X}", paddr, val);
mmio.pi.BusWrite<false>(*this, paddr, val);
break;
case MMIO_REGION:
Util::panic("MMIO Write!");
@@ -569,7 +569,8 @@ template <> u8 Mem::BackupRead<u8>(u32 addr) {
template <> void Mem::BackupWrite<u32>(u32 addr, u32 val) {
switch(saveType) {
case SAVE_NONE:
Util::panic("Accessing cartridge with save type SAVE_NONE in write word");
Util::warn("Accessing cartridge with save type SAVE_NONE in write word");
break;
case SAVE_EEPROM_4k: case SAVE_EEPROM_16k:
Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word");
case SAVE_FLASH_1m:
@@ -585,7 +586,8 @@ template <> void Mem::BackupWrite<u32>(u32 addr, u32 val) {
template <> void Mem::BackupWrite<u8>(u32 addr, u8 val) {
switch(saveType) {
case SAVE_NONE:
Util::panic("Accessing cartridge with save type SAVE_NONE in write word");
Util::warn("Accessing cartridge with save type SAVE_NONE in write word");
break;
case SAVE_EEPROM_4k: case SAVE_EEPROM_16k:
Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word");
case SAVE_FLASH_1m:

View File

@@ -1,4 +1,5 @@
#include <Mem.hpp>
#include <cassert>
namespace n64 {
constexpr auto FLASH_SIZE = 1_mb;
@@ -159,10 +160,11 @@ template <> void Flash::Write<u8>(u32 index, u8 val) {
case FlashState::Idle: Util::panic("Invalid FlashState::Idle with Write<u8>");
case FlashState::Status: Util::panic("Invalid FlashState::Status with Write<u8>");
case FlashState::Erase: Util::panic("Invalid FlashState::Erase with Write<u8>");
case FlashState::Read: Util::panic("Invalid FlashState::Read with Write<u8>");
case FlashState::Write:
assert(index <= 0x7F && "Out of range flash Write8");
writeBuf[index] = val;
break;
case FlashState::Read: Util::panic("Invalid FlashState::Read with Write<u8>");
default: Util::warn("Invalid flash state on Write<u8>: {:02X}", static_cast<u8>(state));
}
}

View File

@@ -62,7 +62,7 @@ template<> auto PI::BusRead<u8, true>(Mem& mem, u32 addr) -> u8 {
case REGION_PI_ROM: {
// round to nearest 4 byte boundary, keeping old LSB
u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
if (index > mem.rom.size) {
if (index >= mem.rom.size) {
Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size);
return 0xFF;
}
@@ -92,7 +92,7 @@ template<> auto PI::BusRead<u8, false>(Mem& mem, u32 addr) -> u8 {
addr = (addr + 2) & ~2;
// round to nearest 4 byte boundary, keeping old LSB
u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
if (index > mem.rom.size) {
if (index >= mem.rom.size) {
Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size);
return 0xFF;
}
@@ -103,33 +103,32 @@ template<> auto PI::BusRead<u8, false>(Mem& mem, u32 addr) -> u8 {
}
}
template<> void PI::BusWrite<u8, true>(Mem& mem, u32 addr, u8 val) {
template<> void PI::BusWrite<u8, true>(Mem& mem, u32 addr, u32 val) {
switch (addr) {
case REGION_PI_UNKNOWN:
Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
case REGION_PI_64DD_REG:
if (addr == 0x05000020) {
fprintf(stderr, "%c", val);
}
else {
Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr);
}
return;
case REGION_PI_64DD_ROM:
Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
case REGION_PI_SRAM:
mem.BackupWrite<u8>(addr - SREGION_PI_SRAM, val);
return;
case REGION_PI_ROM:
Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
return;
default:
Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
case REGION_PI_UNKNOWN:
Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
case REGION_PI_64DD_REG:
if (addr == 0x05000020) {
fprintf(stderr, "%c", val);
} else {
Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr);
}
break;
case REGION_PI_64DD_ROM:
Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
case REGION_PI_SRAM:
mem.BackupWrite<u8>(addr - SREGION_PI_SRAM, val);
break;
case REGION_PI_ROM:
Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
break;
default:
Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
}
}
template<> void PI::BusWrite<u8, false>(Mem& mem, u32 addr, u8 val) {
int latch_shift = 24 - (addr & 1) * 8;
template<> void PI::BusWrite<u8, false>(Mem& mem, u32 addr, u32 val) {
u8 latch_shift = 24 - (addr & 1) * 8;
if (!WriteLatch(val << latch_shift) && addr != 0x05000020) [[unlikely]] {
return;
@@ -169,7 +168,7 @@ template <> auto PI::BusRead<u16, true>(Mem& mem, u32 addr) -> u16 {
return BusRead<u16, false>(mem, addr);
}
template <> void PI::BusWrite<u16, false>(Mem&, u32 addr, u16 val) {
template <> void PI::BusWrite<u16, false>(Mem&, u32 addr, u32 val) {
if (!WriteLatch(val << 16)) [[unlikely]] {
return;
}
@@ -191,7 +190,7 @@ template <> void PI::BusWrite<u16, false>(Mem&, u32 addr, u16 val) {
}
}
template <> void PI::BusWrite<u16, true>(Mem& mem, u32 addr, u16 val) {
template <> void PI::BusWrite<u16, true>(Mem& mem, u32 addr, u32 val) {
BusWrite<u16, false>(mem, addr, val);
}
@@ -220,8 +219,7 @@ template <> auto PI::BusRead<u32, false>(Mem& mem, u32 addr) -> u32 {
return htobe32(Util::ReadAccess<u32>(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER));
case CART_ISVIEWER_FLUSH:
Util::panic("Read from ISViewer flush!");
default:
Util::panic("Read from unknown address {:08X} in REGION_PI_ROM!", addr);
default: break;
}
Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index);
return 0;
@@ -283,6 +281,7 @@ template <> void PI::BusWrite<u32, false>(Mem& mem, u32 addr, u32 val) {
}
default:
if (!WriteLatch(val)) [[unlikely]] {
Util::warn("Couldn't latch PI bus, ignoring write to REGION_PI_ROM");
return;
}
Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
@@ -293,7 +292,8 @@ template <> void PI::BusWrite<u32, false>(Mem& mem, u32 addr, u32 val) {
}
}
template <> void PI::BusWrite<u32, true>(Mem& mem, u32 addr, u32 val) {
template <>
void PI::BusWrite<u32, true>(Mem& mem, u32 addr, u32 val) {
BusWrite<u32, false>(mem, addr, val);
}
@@ -327,7 +327,7 @@ template <> auto PI::BusRead<u64, true>(Mem& mem, u32 addr) -> u64 {
return BusRead<u64, false>(mem, addr);
}
template <> void PI::BusWrite<u64, false>(Mem&, u32 addr, u64 val) {
template <> void PI::BusWrite<false>(Mem&, u32 addr, u64 val) {
if (!WriteLatch(val >> 32)) [[unlikely]] {
return;
}
@@ -349,8 +349,8 @@ template <> void PI::BusWrite<u64, false>(Mem&, u32 addr, u64 val) {
}
}
template <> void PI::BusWrite<u64, true>(Mem& mem, u32 addr, u64 val) {
BusWrite<u64, false>(mem, addr, val);
template <> void PI::BusWrite<true>(Mem& mem, u32 addr, u64 val) {
BusWrite<false>(mem, addr, val);
}
auto PI::Read(MI& mi, u32 addr) const -> u32 {

View File

@@ -14,7 +14,9 @@ struct PI {
void Write(Mem&, Registers&, u32, u32);
template<typename T, bool isDma>
void BusWrite(Mem&, u32, T);
void BusWrite(Mem&, u32, u32);
template<bool isDma>
void BusWrite(Mem&, u32, u64);
template<typename T, bool isDma>
auto BusRead(Mem&, u32) -> T;

View File

@@ -40,12 +40,12 @@ void SI::DMA(Mem& mem, Registers& regs) const {
for(int i = 0; i < 64; i++) {
mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = si.pif.Read(si.pifAddr + i);
}
//Util::debug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", si.pifAddr, si.dramAddr);
Util::trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", si.pifAddr, si.dramAddr);
} else {
for(int i = 0; i < 64; i++) {
si.pif.Write(si.pifAddr + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)]);
}
//Util::debug("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", si.dramAddr, si.pifAddr);
Util::trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", si.dramAddr, si.pifAddr);
si.pif.ProcessCommands(mem);
}
InterruptRaise(mem.mmio.mi, regs, Interrupt::SI);

View File

@@ -107,6 +107,7 @@ struct Cop1 {
void SetCauseDivisionByZero();
void SetCauseOverflow();
void SetCauseInvalid();
int fp_class=0;
private:
template <typename T> auto FGR(Cop0Status&, u32) -> T&;
void decodeInterp(Interpreter&, u32);

View File

@@ -121,7 +121,7 @@ void Cop1::SetCauseInvalid() {
#define PUSHROUNDING int orig_round = PushRoundingMode(fcr31)
#define POPROUNDING fesetround(orig_round)
#define OP_CheckExcept(op) do { PUSHROUNDING; feclearexcept(FE_ALL_EXCEPT); op; SetFPUCauseRaised(regs, fetestexcept(FE_ALL_EXCEPT)); POPROUNDING; } while(0)
#define OP_CheckExcept(op) do { feclearexcept(FE_ALL_EXCEPT); PUSHROUNDING; op; SetFPUCauseRaised(regs, fetestexcept(FE_ALL_EXCEPT)); POPROUNDING; } while(0)
#define CVT_OP_CheckExcept(op) do { feclearexcept(FE_ALL_EXCEPT); op; SetFPUCauseCVTRaised(regs, fetestexcept(FE_ALL_EXCEPT)); CheckFPUException(); } while(0)
#define OP(T, op) do { \
@@ -138,7 +138,8 @@ void Cop1::SetCauseInvalid() {
template <typename T>
FORCE_INLINE void SetCauseByArgWCVT(Registers& regs, T f) {
switch (std::fpclassify(f)) {
regs.cop1.fp_class = std::fpclassify(f);
switch (regs.cop1.fp_class) {
case FP_NAN:
case FP_INFINITE:
case FP_SUBNORMAL:
@@ -161,7 +162,8 @@ FORCE_INLINE void SetCauseByArgWCVT(Registers& regs, T f) {
template <typename T>
FORCE_INLINE void SetCauseByArgLCVT(Registers& regs, T f) {
switch (std::fpclassify(f)) {
regs.cop1.fp_class = std::fpclassify(f);
switch (regs.cop1.fp_class) {
case FP_NAN:
case FP_INFINITE:
case FP_SUBNORMAL:
@@ -190,7 +192,7 @@ FORCE_INLINE void SetFPUCauseRaised(Registers& regs, int raised) {
return;
}
if (raised & FE_UNDERFLOW) {
if (((raised & FE_UNDERFLOW) != 0) || regs.cop1.fp_class == FP_SUBNORMAL) {
if (!regs.cop1.fcr31.fs || regs.cop1.fcr31.enable_underflow || regs.cop1.fcr31.enable_inexact_operation) {
regs.cop1.SetCauseUnimplemented();
return;
@@ -245,8 +247,8 @@ FORCE_INLINE bool isqnan(T f) {
template <typename T>
FORCE_INLINE void SetCauseByArg(Registers& regs, T f) {
int c = std::fpclassify(f);
switch(c) {
regs.cop1.fp_class = std::fpclassify(f);
switch(regs.cop1.fp_class) {
case FP_NAN:
if(isqnan(f)) {
regs.cop1.SetCauseInvalid();
@@ -265,7 +267,7 @@ FORCE_INLINE void SetCauseByArg(Registers& regs, T f) {
case FP_NORMAL:
break; // No-op, these are fine.
default:
Util::panic("Unknown floating point classification: {}", c);
Util::panic("Unknown floating point classification: {}", regs.cop1.fp_class);
}
}
@@ -274,7 +276,7 @@ FORCE_INLINE void SetCauseByArg(Registers& regs, T f) {
template <typename T>
FORCE_INLINE void SetCauseOnResult(Registers& regs, T& d) {
Cop1& cop1 = regs.cop1;
int classification = std::fpclassify(d);
regs.cop1.fp_class = std::fpclassify(d);
T magic, min;
if constexpr(std::is_same_v<T, float>) {
u32 c = 0x7FBFFFFF;
@@ -285,7 +287,7 @@ FORCE_INLINE void SetCauseOnResult(Registers& regs, T& d) {
magic = U64_TO_D(c);
min = DBL_MIN;
}
switch (classification) {
switch (regs.cop1.fp_class) {
case FP_NAN:
d = magic; // set result to sNAN
break;
@@ -324,7 +326,7 @@ FORCE_INLINE void SetCauseOnResult(Registers& regs, T& d) {
case FP_NORMAL:
break; // No-op, these are fine.
default:
Util::panic("Unknown FP classification: {}", classification);
Util::panic("Unknown FP classification: {}", regs.cop1.fp_class);
}
}