fix buncha things, can't be assed to list
This commit is contained in:
@@ -63,7 +63,7 @@ void Dynarec::Recompile(Mem& mem, u32 pc) {
|
||||
while(!prevBranch) {
|
||||
instrInBlock++;
|
||||
prevBranch = branch;
|
||||
u32 instr = mem.Read32<false>(regs, loopPC, loopPC);
|
||||
u32 instr = mem.Read32(regs, loopPC);
|
||||
|
||||
emitBreakpoint();
|
||||
code.mov(rdi, (uintptr_t)®s);
|
||||
@@ -104,8 +104,11 @@ int Dynarec::Step(Mem &mem) {
|
||||
regs.delaySlot = false;
|
||||
|
||||
u32 pc{};
|
||||
|
||||
if(!MapVAddr(regs, LOAD, regs.pc, pc)) {
|
||||
Util::panic("[RECOMPILER] Failed to translate PC to physical address (v: {:08X})\n", regs.pc);
|
||||
HandleTLBException(regs, regs.pc);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(blockCache[pc >> 20]) {
|
||||
|
||||
@@ -29,13 +29,20 @@ void Interpreter::Step(Mem& mem) {
|
||||
regs.prevDelaySlot = regs.delaySlot;
|
||||
regs.delaySlot = false;
|
||||
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, LOAD, regs.pc, paddr)) {
|
||||
HandleTLBException(regs, regs.pc);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 instruction = mem.Read32(regs, paddr);
|
||||
|
||||
if(ShouldServiceInterrupt(regs)) {
|
||||
FireException(regs, ExceptionCode::Interrupt, 0, false);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 instruction = mem.Read32(regs, regs.pc, regs.pc);
|
||||
|
||||
regs.oldPC = regs.pc;
|
||||
regs.pc = regs.nextPC;
|
||||
regs.nextPC += 4;
|
||||
|
||||
@@ -17,7 +17,8 @@ void Mem::Reset() {
|
||||
std::fill(readPages.begin(), readPages.end(), 0);
|
||||
std::fill(writePages.begin(), writePages.end(), 0);
|
||||
|
||||
for(int i = 0; i < 2048; i++) {
|
||||
int i = 0;
|
||||
for(i = 0; i < RDRAM_SIZE / PAGE_SIZE; i++) {
|
||||
const auto addr = (i * PAGE_SIZE) & RDRAM_DSIZE;
|
||||
const auto pointer = (uintptr_t) &mmio.rdp.rdram[addr];
|
||||
readPages[i] = pointer;
|
||||
@@ -66,6 +67,12 @@ CartInfo Mem::LoadROM(const std::string& filename) {
|
||||
SetCICType(result.cicType, cicChecksum);
|
||||
result.isPAL = IsROMPAL();
|
||||
|
||||
for(int i = 0; i < sizeAdjusted / PAGE_SIZE; i++) {
|
||||
const auto addr = (i * PAGE_SIZE) & romMask;
|
||||
const auto pointer = (uintptr_t) &cart[addr];
|
||||
readPages[0x10000 + i] = pointer;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -89,13 +96,9 @@ bool MapVAddr(Registers& regs, TLBAccessType accessType, u64 vaddr, u32& paddr)
|
||||
template bool MapVAddr<true>(Registers& regs, TLBAccessType accessType, u64 vaddr, u32& paddr);
|
||||
template bool MapVAddr<false>(Registers& regs, TLBAccessType accessType, u64 vaddr, u32& paddr);
|
||||
|
||||
template <bool tlb>
|
||||
u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
}
|
||||
u8 Mem::Read8(n64::Registers ®s, u32 paddr) {
|
||||
if(paddr >= 0x10000000 && paddr <= 0x1FBFFFFF)
|
||||
paddr = (paddr + 2) & ~2;
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
const auto offset = paddr & 0xFFF;
|
||||
@@ -123,7 +126,6 @@ u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
return (w >> (offs * 8)) & 0xff;
|
||||
}
|
||||
case 0x10000000 ... 0x1FBFFFFF:
|
||||
paddr = (paddr + 2) & ~2;
|
||||
return cart[BYTE_ADDRESS(paddr) & romMask];
|
||||
case 0x1FC00000 ... 0x1FC007BF:
|
||||
return pifBootrom[BYTE_ADDRESS(paddr) - 0x1FC00000];
|
||||
@@ -140,13 +142,9 @@ u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
}
|
||||
u16 Mem::Read16(n64::Registers ®s, u32 paddr) {
|
||||
if(paddr >= 0x10000000 && paddr <= 0x1FBFFFFF)
|
||||
paddr = (paddr + 2) & ~3;
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
const auto offset = paddr & 0xFFF;
|
||||
@@ -169,7 +167,6 @@ u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
case 0x04500000 ... 0x048FFFFF:
|
||||
return mmio.Read(paddr);
|
||||
case 0x10000000 ... 0x1FBFFFFF:
|
||||
paddr = (paddr + 2) & ~3;
|
||||
return Util::ReadAccess<u16>(cart.data(), HALF_ADDRESS(paddr) & romMask);
|
||||
case 0x1FC00000 ... 0x1FC007BF:
|
||||
return Util::ReadAccess<u16>(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000);
|
||||
@@ -186,14 +183,7 @@ u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
u32 Mem::Read32(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
}
|
||||
|
||||
u32 Mem::Read32(n64::Registers ®s, u32 paddr) {
|
||||
const auto page = paddr >> 12;
|
||||
const auto offset = paddr & 0xFFF;
|
||||
const auto pointer = readPages[page];
|
||||
@@ -226,14 +216,7 @@ u32 Mem::Read32(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
}
|
||||
|
||||
u64 Mem::Read64(n64::Registers ®s, u32 paddr) {
|
||||
const auto page = paddr >> 12;
|
||||
const auto offset = paddr & 0xFFF;
|
||||
const auto pointer = readPages[page];
|
||||
@@ -271,35 +254,19 @@ u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc) {
|
||||
}
|
||||
}
|
||||
|
||||
template u8 Mem::Read8<false>(n64::Registers ®s, u64 vaddr, s64 pc);
|
||||
template u8 Mem::Read8<true>(n64::Registers ®s, u64 vaddr, s64 pc);
|
||||
template u16 Mem::Read16<false>(n64::Registers ®s, u64 vaddr, s64 pc);
|
||||
template u16 Mem::Read16<true>(n64::Registers ®s, u64 vaddr, s64 pc);
|
||||
template u32 Mem::Read32<false>(n64::Registers ®s, u64 vaddr, s64 pc);
|
||||
template u32 Mem::Read32<true>(n64::Registers ®s, u64 vaddr, s64 pc);
|
||||
template u64 Mem::Read64<false>(n64::Registers ®s, u64 vaddr, s64 pc);
|
||||
template u64 Mem::Read64<true>(n64::Registers ®s, u64 vaddr, s64 pc);
|
||||
|
||||
template <bool tlb>
|
||||
void Mem::Write8(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
}
|
||||
|
||||
void Mem::Write8(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u32 val) {
|
||||
dyn.InvalidatePage(BYTE_ADDRESS(paddr));
|
||||
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val = val << (8 * (3 - (paddr & 3)));
|
||||
paddr = (paddr & DMEM_DSIZE) & ~3;
|
||||
}
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
auto offset = paddr & 0xFFF;
|
||||
const auto pointer = readPages[page];
|
||||
|
||||
if(pointer) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val = val << (8 * (3 - (paddr & 3)));
|
||||
offset = (offset & DMEM_DSIZE) & ~3;
|
||||
}
|
||||
|
||||
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
|
||||
} else {
|
||||
switch (paddr) {
|
||||
@@ -307,8 +274,6 @@ void Mem::Write8(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s6
|
||||
mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val;
|
||||
break;
|
||||
case 0x04000000 ... 0x0403FFFF:
|
||||
val = val << (8 * (3 - (paddr & 3)));
|
||||
paddr = (paddr & DMEM_DSIZE) & ~3;
|
||||
if (paddr & 0x1000)
|
||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||
else
|
||||
@@ -341,26 +306,19 @@ void Mem::Write8(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s6
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
void Mem::Write16(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false);
|
||||
}
|
||||
|
||||
void Mem::Write16(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u32 val) {
|
||||
dyn.InvalidatePage(HALF_ADDRESS(paddr));
|
||||
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val = val << (16 * !(paddr & 2));
|
||||
paddr &= ~3;
|
||||
}
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
auto offset = paddr & 0xFFF;
|
||||
const auto pointer = readPages[page];
|
||||
|
||||
if(pointer) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val = val << (16 * !(paddr & 2));
|
||||
offset &= ~3;
|
||||
}
|
||||
|
||||
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
||||
} else {
|
||||
switch (paddr) {
|
||||
@@ -368,8 +326,6 @@ void Mem::Write16(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s
|
||||
Util::WriteAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val);
|
||||
break;
|
||||
case 0x04000000 ... 0x0403FFFF:
|
||||
val = val << (16 * !(paddr & 2));
|
||||
paddr &= ~3;
|
||||
if (paddr & 0x1000)
|
||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||
else
|
||||
@@ -402,14 +358,7 @@ void Mem::Write16(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
void Mem::Write32(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false);
|
||||
}
|
||||
|
||||
void Mem::Write32(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u32 val) {
|
||||
dyn.InvalidatePage(paddr);
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
@@ -455,24 +404,18 @@ void Mem::Write32(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u32 val, s
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
void Mem::Write64(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u64 val, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false);
|
||||
}
|
||||
|
||||
void Mem::Write64(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u64 val) {
|
||||
dyn.InvalidatePage(paddr);
|
||||
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val >>= 32;
|
||||
}
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
auto offset = paddr & 0xFFF;
|
||||
const auto pointer = readPages[page];
|
||||
|
||||
if(pointer) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val >>= 32;
|
||||
}
|
||||
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
||||
} else {
|
||||
switch (paddr) {
|
||||
@@ -480,7 +423,6 @@ void Mem::Write64(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u64 val, s
|
||||
Util::WriteAccess<u64>(mmio.rdp.rdram.data(), paddr, val);
|
||||
break;
|
||||
case 0x04000000 ... 0x0403FFFF:
|
||||
val >>= 32;
|
||||
if (paddr & 0x1000)
|
||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||
else
|
||||
@@ -511,21 +453,10 @@ void Mem::Write64(Registers& regs, n64::JIT::Dynarec& dyn, u64 vaddr, u64 val, s
|
||||
}
|
||||
}
|
||||
|
||||
template void Mem::Write8<false>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write8<true>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write16<false>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write16<true>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write32<false>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write32<true>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write64<false>(Registers& regs, JIT::Dynarec&, u64 vaddr, u64 val, s64 pc);
|
||||
template void Mem::Write64<true>(Registers& regs, JIT::Dynarec&, u64 vaddr, u64 val, s64 pc);
|
||||
|
||||
template <bool tlb>
|
||||
void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||
void Mem::Write8(Registers& regs, u32 paddr, u32 val) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val = val << (8 * (3 - (paddr & 3)));
|
||||
paddr = (paddr & DMEM_DSIZE) & ~3;
|
||||
}
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
@@ -533,11 +464,6 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
const auto pointer = readPages[page];
|
||||
|
||||
if(pointer) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val = val << (8 * (3 - (paddr & 3)));
|
||||
offset = (offset & DMEM_DSIZE) & ~3;
|
||||
}
|
||||
|
||||
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
|
||||
} else {
|
||||
switch (paddr) {
|
||||
@@ -545,8 +471,6 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val;
|
||||
break;
|
||||
case 0x04000000 ... 0x0403FFFF:
|
||||
val = val << (8 * (3 - (paddr & 3)));
|
||||
paddr = (paddr & DMEM_DSIZE) & ~3;
|
||||
if (paddr & 0x1000)
|
||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||
else
|
||||
@@ -579,12 +503,10 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false);
|
||||
void Mem::Write16(Registers& regs, u32 paddr, u32 val) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val = val << (16 * !(paddr & 2));
|
||||
paddr &= ~3;
|
||||
}
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
@@ -592,11 +514,6 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
const auto pointer = readPages[page];
|
||||
|
||||
if(pointer) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val = val << (16 * !(paddr & 2));
|
||||
offset &= ~3;
|
||||
}
|
||||
|
||||
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
||||
} else {
|
||||
switch (paddr) {
|
||||
@@ -604,8 +521,6 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
Util::WriteAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val);
|
||||
break;
|
||||
case 0x04000000 ... 0x0403FFFF:
|
||||
val = val << (16 * !(paddr & 2));
|
||||
paddr &= ~3;
|
||||
if (paddr & 0x1000)
|
||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||
else
|
||||
@@ -638,14 +553,7 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false);
|
||||
}
|
||||
|
||||
void Mem::Write32(Registers& regs, u32 paddr, u32 val) {
|
||||
const auto page = paddr >> 12;
|
||||
auto offset = paddr & 0xFFF;
|
||||
const auto pointer = readPages[page];
|
||||
@@ -689,12 +597,9 @@ void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
||||
}
|
||||
}
|
||||
|
||||
template <bool tlb>
|
||||
void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
|
||||
u32 paddr = vaddr;
|
||||
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
|
||||
HandleTLBException(regs, vaddr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false);
|
||||
void Mem::Write64(Registers& regs, u32 paddr, u64 val) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val >>= 32;
|
||||
}
|
||||
|
||||
const auto page = paddr >> 12;
|
||||
@@ -702,9 +607,6 @@ void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
|
||||
const auto pointer = readPages[page];
|
||||
|
||||
if(pointer) {
|
||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||
val >>= 32;
|
||||
}
|
||||
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
||||
} else {
|
||||
switch (paddr) {
|
||||
@@ -712,7 +614,6 @@ void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
|
||||
Util::WriteAccess<u64>(mmio.rdp.rdram.data(), paddr, val);
|
||||
break;
|
||||
case 0x04000000 ... 0x0403FFFF:
|
||||
val >>= 32;
|
||||
if (paddr & 0x1000)
|
||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||
else
|
||||
@@ -742,13 +643,4 @@ void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void Mem::Write8<false>(Registers& regs, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write8<true>(Registers& regs, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write16<false>(Registers& regs, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write16<true>(Registers& regs, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write32<false>(Registers& regs, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write32<true>(Registers& regs, u64 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write64<false>(Registers& regs, u64 vaddr, u64 val, s64 pc);
|
||||
template void Mem::Write64<true>(Registers& regs, u64 vaddr, u64 val, s64 pc);
|
||||
}
|
||||
@@ -28,30 +28,18 @@ struct Mem {
|
||||
return mmio.rdp.rdram.data();
|
||||
}
|
||||
|
||||
template <bool tlb = true>
|
||||
u8 Read8(Registers&, u64, s64);
|
||||
template <bool tlb = true>
|
||||
u16 Read16(Registers&, u64, s64);
|
||||
template <bool tlb = true>
|
||||
u32 Read32(Registers&, u64, s64);
|
||||
template <bool tlb = true>
|
||||
u64 Read64(Registers&, u64, s64);
|
||||
template <bool tlb = true>
|
||||
void Write8(Registers&, JIT::Dynarec&, u64, u32, s64);
|
||||
template <bool tlb = true>
|
||||
void Write16(Registers&, JIT::Dynarec&, u64, u32, s64);
|
||||
template <bool tlb = true>
|
||||
void Write32(Registers&, JIT::Dynarec&, u64, u32, s64);
|
||||
template <bool tlb = true>
|
||||
void Write64(Registers&, JIT::Dynarec&, u64, u64, s64);
|
||||
template <bool tlb = true>
|
||||
void Write8(Registers&, u64, u32, s64);
|
||||
template <bool tlb = true>
|
||||
void Write16(Registers&, u64, u32, s64);
|
||||
template <bool tlb = true>
|
||||
void Write32(Registers&, u64, u32, s64);
|
||||
template <bool tlb = true>
|
||||
void Write64(Registers&, u64, u64, s64);
|
||||
u8 Read8(Registers&, u32);
|
||||
u16 Read16(Registers&, u32);
|
||||
u32 Read32(Registers&, u32);
|
||||
u64 Read64(Registers&, u32);
|
||||
void Write8(Registers&, JIT::Dynarec&, u32, u32);
|
||||
void Write16(Registers&, JIT::Dynarec&, u32, u32);
|
||||
void Write32(Registers&, JIT::Dynarec&, u32, u32);
|
||||
void Write64(Registers&, JIT::Dynarec&, u32, u64);
|
||||
void Write8(Registers&, u32, u32);
|
||||
void Write16(Registers&, u32, u32);
|
||||
void Write32(Registers&, u32, u32);
|
||||
void Write64(Registers&, u32, u64);
|
||||
|
||||
MMIO mmio;
|
||||
u8 pifRam[PIF_RAM_SIZE]{};
|
||||
|
||||
@@ -448,16 +448,13 @@ void lwc1(n64::Registers& regs, Mem& mem, u32 instr) {
|
||||
}
|
||||
|
||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||
if(addr & 3) {
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
||||
HandleTLBException(regs, addr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
u32 data = mem.Read32<false>(regs, physical, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, physical);
|
||||
regs.cop1.SetReg<u32>(regs.cop0, FT(instr), data);
|
||||
}
|
||||
}
|
||||
@@ -469,57 +466,48 @@ void swc1(n64::Registers& regs, Mem& mem, u32 instr) {
|
||||
}
|
||||
|
||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||
if(addr & 3) {
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, STORE, addr, physical)) {
|
||||
HandleTLBException(regs, addr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write32<false>(regs, physical, regs.cop1.GetReg<u32>(regs.cop0, FT(instr)), regs.oldPC);
|
||||
mem.Write32(regs, physical, regs.cop1.GetReg<u32>(regs.cop0, FT(instr)));
|
||||
}
|
||||
}
|
||||
|
||||
void ldc1(n64::Registers& regs, Mem& mem, u32 instr) {
|
||||
if(!regs.cop0.status.cu1) {
|
||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||
if(addr & 7) {
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
||||
HandleTLBException(regs, addr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
u64 data = mem.Read64<false>(regs, physical, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, physical);
|
||||
regs.cop1.SetReg<u64>(regs.cop0, FT(instr), data);
|
||||
}
|
||||
}
|
||||
|
||||
void sdc1(n64::Registers& regs, Mem& mem, u32 instr) {
|
||||
if(!regs.cop0.status.cu1) {
|
||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||
if(addr & 7) {
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, STORE, addr, physical)) {
|
||||
HandleTLBException(regs, addr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write64<false>(regs, physical, regs.cop1.GetReg<u64>(regs.cop0, FT(instr)), regs.oldPC);
|
||||
mem.Write64(regs, physical, regs.cop1.GetReg<u64>(regs.cop0, FT(instr)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <dynarec/instructions.hpp>
|
||||
#include <Registers.hpp>
|
||||
#include <core/Dynarec.hpp>
|
||||
|
||||
#define se_imm(x) ((s16)((x) & 0xFFFF))
|
||||
#define check_address_error(mask, addr) (((!regs.cop0.is_64bit_addressing) && (s32)(addr) != (addr)) || (((addr) & (mask)) != 0))
|
||||
@@ -41,7 +40,6 @@ void addiu(Registers& regs, u32 instr) {
|
||||
s16 imm = (s16)(instr);
|
||||
s32 result = rs + imm;
|
||||
regs.gpr[RT(instr)] = result;
|
||||
Util::print("addiu {:08X}, {:04X} = {:08X} [reg: {:016X}]\n", (u32)rs, imm, (u32)result, (u64)regs.gpr[RT(instr)]);
|
||||
}
|
||||
|
||||
void dadd(Registers& regs, u32 instr) {
|
||||
@@ -147,7 +145,6 @@ void ddivu(Registers& regs, u32 instr) {
|
||||
}
|
||||
|
||||
void branch(Registers& regs, bool cond, s64 address) {
|
||||
//Util::debug("\t\tJIT branch from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address);
|
||||
regs.delaySlot = true;
|
||||
if (cond) {
|
||||
regs.nextPC = address;
|
||||
@@ -157,10 +154,8 @@ void branch(Registers& regs, bool cond, s64 address) {
|
||||
void branch_likely(Registers& regs, bool cond, s64 address) {
|
||||
regs.delaySlot = true;
|
||||
if (cond) {
|
||||
//Util::debug("\t\tJIT branch likely taken from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address);
|
||||
regs.nextPC = address;
|
||||
} else {
|
||||
//Util::debug("\t\tJIT branch likely not taken from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address);
|
||||
regs.SetPC(regs.nextPC);
|
||||
}
|
||||
}
|
||||
@@ -199,18 +194,30 @@ void lui(Registers& regs, u32 instr) {
|
||||
|
||||
void lb(Registers& regs, Mem& mem, u32 instr) {
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
regs.gpr[RT(instr)] = (s8)mem.Read8(regs, address, regs.oldPC);
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s8)mem.Read8(regs, paddr);
|
||||
}
|
||||
}
|
||||
|
||||
void lh(Registers& regs, Mem& mem, u32 instr) {
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b1)) {
|
||||
if ((address & 0b1) > 0) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address, regs.oldPC);
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address);
|
||||
}
|
||||
}
|
||||
|
||||
void lw(Registers& regs, Mem& mem, u32 instr) {
|
||||
@@ -222,23 +229,28 @@ void lw(Registers& regs, Mem& mem, u32 instr) {
|
||||
return;
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
u32 physical = 0;
|
||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s32)mem.Read32<false>(regs, physical, regs.oldPC);
|
||||
regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical);
|
||||
}
|
||||
}
|
||||
|
||||
void ll(Registers& regs, Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u32 physical;
|
||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s32)mem.Read32<false>(regs, physical, regs.oldPC);
|
||||
if ((address & 0b11) > 0) {
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
return;
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical);
|
||||
}
|
||||
}
|
||||
|
||||
regs.cop0.llbit = true;
|
||||
@@ -254,7 +266,7 @@ void lwl(Registers& regs, Mem& mem, u32 instr) {
|
||||
} else {
|
||||
u32 shift = 8 * ((address ^ 0) & 3);
|
||||
u32 mask = 0xFFFFFFFF << shift;
|
||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, paddr & ~3);
|
||||
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||
regs.gpr[RT(instr)] = result;
|
||||
}
|
||||
@@ -269,7 +281,7 @@ void lwr(Registers& regs, Mem& mem, u32 instr) {
|
||||
} else {
|
||||
u32 shift = 8 * ((address ^ 3) & 3);
|
||||
u32 mask = 0xFFFFFFFF >> shift;
|
||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, paddr & ~3);
|
||||
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||
regs.gpr[RT(instr)] = result;
|
||||
}
|
||||
@@ -283,22 +295,30 @@ void ld(Registers& regs, Mem& mem, u32 instr) {
|
||||
return;
|
||||
}
|
||||
|
||||
s64 value = mem.Read64(regs, address, regs.oldPC);
|
||||
s64 value = mem.Read64(regs, address);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
}
|
||||
|
||||
void lld(Registers& regs, Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
|
||||
FireException(regs, ExceptionCode::ReservedInstruction, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u32 paddr;
|
||||
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = mem.Read64<false>(regs, paddr, regs.oldPC);
|
||||
if ((address & 0b111) > 0) {
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = mem.Read64(regs, paddr);
|
||||
regs.cop0.llbit = true;
|
||||
regs.cop0.LLAddr = paddr >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
regs.cop0.llbit = true;
|
||||
regs.cop0.LLAddr = paddr >> 4;
|
||||
}
|
||||
|
||||
void ldl(Registers& regs, Mem& mem, u32 instr) {
|
||||
@@ -310,7 +330,7 @@ void ldl(Registers& regs, Mem& mem, u32 instr) {
|
||||
} else {
|
||||
s32 shift = 8 * ((address ^ 0) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, paddr & ~7);
|
||||
s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||
regs.gpr[RT(instr)] = result;
|
||||
}
|
||||
@@ -325,7 +345,7 @@ void ldr(Registers& regs, Mem& mem, u32 instr) {
|
||||
} else {
|
||||
s32 shift = 8 * ((address ^ 7) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, paddr & ~7);
|
||||
s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||
regs.gpr[RT(instr)] = result;
|
||||
}
|
||||
@@ -333,7 +353,7 @@ void ldr(Registers& regs, Mem& mem, u32 instr) {
|
||||
|
||||
void lbu(Registers& regs, Mem& mem, u32 instr) {
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u8 value = mem.Read8(regs, address, regs.oldPC);
|
||||
u8 value = mem.Read8(regs, address);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
}
|
||||
|
||||
@@ -345,7 +365,7 @@ void lhu(Registers& regs, Mem& mem, u32 instr) {
|
||||
return;
|
||||
}
|
||||
|
||||
u16 value = mem.Read16(regs, address, regs.oldPC);
|
||||
u16 value = mem.Read16(regs, address);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
}
|
||||
|
||||
@@ -357,28 +377,36 @@ void lwu(Registers& regs, Mem& mem, u32 instr) {
|
||||
return;
|
||||
}
|
||||
|
||||
u32 value = mem.Read32(regs, address, regs.oldPC);
|
||||
u32 value = mem.Read32(regs, address);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
}
|
||||
|
||||
void sb(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
mem.Write8(regs, dyn, address, regs.gpr[RT(instr)], regs.oldPC);
|
||||
mem.Write8(regs, dyn, address, regs.gpr[RT(instr)]);
|
||||
}
|
||||
|
||||
void sc(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b11)) {
|
||||
HandleTLBException(regs, address);
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
|
||||
if ((address & 0b11) > 0) {
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if(regs.cop0.llbit) {
|
||||
mem.Write32(regs, dyn, address, regs.gpr[RT(instr)], regs.oldPC);
|
||||
regs.cop0.llbit = false;
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, STORE, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write32(regs, dyn, paddr, regs.gpr[RT(instr)]);
|
||||
regs.gpr[RT(instr)] = 1;
|
||||
}
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = 0;
|
||||
}
|
||||
|
||||
regs.gpr[RT(instr)] = (u64)regs.cop0.llbit;
|
||||
regs.cop0.llbit = false;
|
||||
}
|
||||
|
||||
void scd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
@@ -390,7 +418,7 @@ void scd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
}
|
||||
|
||||
if(regs.cop0.llbit) {
|
||||
mem.Write64(regs, dyn, address, regs.gpr[RT(instr)], regs.oldPC);
|
||||
mem.Write64(regs, dyn, address, regs.gpr[RT(instr)]);
|
||||
}
|
||||
|
||||
regs.gpr[RT(instr)] = (s64)((u64)regs.cop0.llbit);
|
||||
@@ -410,7 +438,7 @@ void sh(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write16<false>(regs, dyn, physical, regs.gpr[RT(instr)], regs.oldPC);
|
||||
mem.Write16(regs, dyn, physical, regs.gpr[RT(instr)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,7 +456,7 @@ void sw(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write32<false>(regs, dyn, physical, regs.gpr[RT(instr)], regs.oldPC);
|
||||
mem.Write32(regs, dyn, physical, regs.gpr[RT(instr)]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,7 +473,7 @@ void sd(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write64<false>(regs, dyn, physical, regs.gpr[RT(instr)], regs.oldPC);
|
||||
mem.Write64(regs, dyn, physical, regs.gpr[RT(instr)]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -459,9 +487,9 @@ void sdl(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
} else {
|
||||
s32 shift = 8 * ((address ^ 0) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, paddr & ~7);
|
||||
u64 rt = regs.gpr[RT(instr)];
|
||||
mem.Write64<false>(regs, dyn, paddr & ~7, (data & ~mask) | (rt >> shift), regs.oldPC);
|
||||
mem.Write64(regs, dyn, paddr & ~7, (data & ~mask) | (rt >> shift));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,9 +502,9 @@ void sdr(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
} else {
|
||||
s32 shift = 8 * ((address ^ 7) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, paddr & ~7);
|
||||
u64 rt = regs.gpr[RT(instr)];
|
||||
mem.Write64<false>(regs, dyn, paddr & ~7, (data & ~mask) | (rt << shift), regs.oldPC);
|
||||
mem.Write64(regs, dyn, paddr & ~7, (data & ~mask) | (rt << shift));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,9 +517,9 @@ void swl(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
} else {
|
||||
u32 shift = 8 * ((address ^ 0) & 3);
|
||||
u32 mask = 0xFFFFFFFF >> shift;
|
||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, paddr & ~3);
|
||||
u32 rt = regs.gpr[RT(instr)];
|
||||
mem.Write32<false>(regs, dyn, paddr & ~3, (data & ~mask) | (rt >> shift), regs.oldPC);
|
||||
mem.Write32(regs, dyn, paddr & ~3, (data & ~mask) | (rt >> shift));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,9 +532,9 @@ void swr(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||
} else {
|
||||
u32 shift = 8 * ((address ^ 3) & 3);
|
||||
u32 mask = 0xFFFFFFFF << shift;
|
||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, paddr & ~3);
|
||||
u32 rt = regs.gpr[RT(instr)];
|
||||
mem.Write32<false>(regs, dyn, paddr & ~3, (data & ~mask) | (rt << shift), regs.oldPC);
|
||||
mem.Write32(regs, dyn, paddr & ~3, (data & ~mask) | (rt << shift));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,12 +553,8 @@ void nor(Registers& regs, u32 instr) {
|
||||
}
|
||||
|
||||
void j(Registers& regs, u32 instr) {
|
||||
s32 target = (instr & 0x3ffffff) << 2;
|
||||
s64 address = (regs.oldPC & ~0xfffffff) | target;
|
||||
if (check_address_error(address, 0b11)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::DataBusError, 0, true);
|
||||
}
|
||||
u64 target = (instr & 0x3ffffff) << 2;
|
||||
u64 address = ((regs.pc - 4) & ~0xfffffff) | target;
|
||||
|
||||
branch(regs, true, address);
|
||||
}
|
||||
@@ -686,7 +710,7 @@ void jr(Registers& regs, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)];
|
||||
if (check_address_error(address, 0b11)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::DataBusError, 0, true);
|
||||
}
|
||||
|
||||
branch(regs, true, address);
|
||||
@@ -697,7 +721,7 @@ void dsub(Registers& regs, u32 instr) {
|
||||
s64 rs = regs.gpr[RS(instr)];
|
||||
s64 result = rs - rt;
|
||||
if(check_signed_underflow(rs, rt, result)) {
|
||||
FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::Overflow, 0, true);
|
||||
} else {
|
||||
regs.gpr[RD(instr)] = result;
|
||||
}
|
||||
@@ -715,7 +739,7 @@ void sub(Registers& regs, u32 instr) {
|
||||
s32 rs = regs.gpr[RS(instr)];
|
||||
s32 result = rs - rt;
|
||||
if(check_signed_underflow(rs, rt, result)) {
|
||||
FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::Overflow, 0, true);
|
||||
} else {
|
||||
regs.gpr[RD(instr)] = result;
|
||||
}
|
||||
@@ -778,7 +802,7 @@ void mthi(Registers& regs, u32 instr) {
|
||||
|
||||
void trap(Registers& regs, bool cond) {
|
||||
if(cond) {
|
||||
FireException(regs, ExceptionCode::Trap, 0, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::Trap, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,4 +822,13 @@ void dmtc2(Dynarec& dyn, Registers& regs, u32 instr) {
|
||||
void dmfc2(Dynarec& dyn, Registers& regs, u32 instr) {
|
||||
regs.gpr[RT(instr)] = dyn.cop2Latch;
|
||||
}
|
||||
|
||||
void ctc2(u32) {
|
||||
|
||||
}
|
||||
|
||||
void cfc2(u32) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,7 +31,7 @@ void Cop0::eret(Registers& regs) {
|
||||
}
|
||||
|
||||
|
||||
void Cop0::tlbr(Registers& regs) {
|
||||
void Cop0::tlbr() {
|
||||
u8 Index = index & 0b111111;
|
||||
if (Index >= 32) {
|
||||
Util::panic("TLBR with TLB index {}", index);
|
||||
@@ -48,7 +48,7 @@ void Cop0::tlbr(Registers& regs) {
|
||||
pageMask.raw = entry.pageMask.raw;
|
||||
}
|
||||
|
||||
void Cop0::tlbw(int index_, Registers& regs) {
|
||||
void Cop0::tlbw(int index_) {
|
||||
PageMask page_mask{};
|
||||
page_mask = pageMask;
|
||||
u32 top = page_mask.mask & 0xAAA;
|
||||
|
||||
@@ -450,16 +450,13 @@ void Cop1::lwc1(Registers& regs, Mem& mem, u32 instr) {
|
||||
}
|
||||
|
||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||
if(addr & 3) {
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
||||
HandleTLBException(regs, addr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
u32 data = mem.Read32<false>(regs, physical, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, physical);
|
||||
SetReg<u32>(regs.cop0, FT(instr), data);
|
||||
}
|
||||
}
|
||||
@@ -471,16 +468,13 @@ void Cop1::swc1(Registers& regs, Mem& mem, u32 instr) {
|
||||
}
|
||||
|
||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||
if(addr & 3) {
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, STORE, addr, physical)) {
|
||||
HandleTLBException(regs, addr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write32<false>(regs, physical, GetReg<u32>(regs.cop0, FT(instr)), regs.oldPC);
|
||||
mem.Write32(regs, physical, GetReg<u32>(regs.cop0, FT(instr)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,37 +485,31 @@ void Cop1::ldc1(Registers& regs, Mem& mem, u32 instr) {
|
||||
}
|
||||
|
||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||
if(addr & 7) {
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
||||
HandleTLBException(regs, addr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
u64 data = mem.Read64<false>(regs, physical, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, physical);
|
||||
SetReg<u64>(regs.cop0, FT(instr), data);
|
||||
}
|
||||
}
|
||||
|
||||
void Cop1::sdc1(Registers& regs, Mem& mem, u32 instr) {
|
||||
if(!regs.cop0.status.cu1) {
|
||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||
if(addr & 7) {
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, STORE, addr, physical)) {
|
||||
HandleTLBException(regs, addr);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write64<false>(regs, physical, GetReg<u64>(regs.cop0, FT(instr)), regs.oldPC);
|
||||
mem.Write64(regs, physical, GetReg<u64>(regs.cop0, FT(instr)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <core/Interpreter.hpp>
|
||||
|
||||
#define se_imm(x) ((s16)((x) & 0xFFFF))
|
||||
#define check_address_error(mask, addr) (((!regs.cop0.is_64bit_addressing) && (s32)(addr) != (addr)) || (((addr) & (mask)) != 0))
|
||||
#define check_address_error(mask, vaddr) (((!regs.cop0.is_64bit_addressing) && (s32)(vaddr) != (vaddr)) || (((vaddr) & (mask)) != 0))
|
||||
#define check_signed_overflow(op1, op2, res) (((~((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
|
||||
#define check_signed_underflow(op1, op2, res) (((((op1) ^ (op2)) & ((op1) ^ (res))) >> ((sizeof(res) * 8) - 1)) & 1)
|
||||
|
||||
@@ -194,46 +194,63 @@ void Interpreter::lui(u32 instr) {
|
||||
|
||||
void Interpreter::lb(Mem& mem, u32 instr) {
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
regs.gpr[RT(instr)] = (s8)mem.Read8(regs, address, regs.oldPC);
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s8)mem.Read8(regs, paddr);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::lh(Mem& mem, u32 instr) {
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b1)) {
|
||||
if ((address & 0b1) > 0) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, address, regs.oldPC);
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s16)mem.Read16(regs, paddr);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::lw(Mem& mem, u32 instr) {
|
||||
s16 offset = instr;
|
||||
u64 address = regs.gpr[RS(instr)] + offset;
|
||||
if (check_address_error(address, 0b11)) {
|
||||
if (check_address_error(0b11, address)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
u32 physical = 0;
|
||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s32)mem.Read32<false>(regs, physical, regs.oldPC);
|
||||
regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::ll(Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u32 physical;
|
||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s32)mem.Read32<false>(regs, physical, regs.oldPC);
|
||||
if ((address & 0b11) > 0) {
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
return;
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = (s32)mem.Read32(regs, physical);
|
||||
}
|
||||
}
|
||||
|
||||
regs.cop0.llbit = true;
|
||||
@@ -249,7 +266,7 @@ void Interpreter::lwl(Mem& mem, u32 instr) {
|
||||
} else {
|
||||
u32 shift = 8 * ((address ^ 0) & 3);
|
||||
u32 mask = 0xFFFFFFFF << shift;
|
||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, paddr & ~3);
|
||||
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||
regs.gpr[RT(instr)] = result;
|
||||
}
|
||||
@@ -264,7 +281,7 @@ void Interpreter::lwr(Mem& mem, u32 instr) {
|
||||
} else {
|
||||
u32 shift = 8 * ((address ^ 3) & 3);
|
||||
u32 mask = 0xFFFFFFFF >> shift;
|
||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, paddr & ~3);
|
||||
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||
regs.gpr[RT(instr)] = result;
|
||||
}
|
||||
@@ -272,28 +289,42 @@ void Interpreter::lwr(Mem& mem, u32 instr) {
|
||||
|
||||
void Interpreter::ld(Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b111)) {
|
||||
if (check_address_error(0b111, address)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
s64 value = mem.Read64(regs, address, regs.oldPC);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
s64 value = mem.Read64(regs, paddr);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::lld(Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
|
||||
FireException(regs, ExceptionCode::ReservedInstruction, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u32 paddr;
|
||||
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = mem.Read64<false>(regs, paddr, regs.oldPC);
|
||||
if ((address & 0b111) > 0) {
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = mem.Read64(regs, paddr);
|
||||
regs.cop0.llbit = true;
|
||||
regs.cop0.LLAddr = paddr >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
regs.cop0.llbit = true;
|
||||
regs.cop0.LLAddr = paddr >> 4;
|
||||
}
|
||||
|
||||
void Interpreter::ldl(Mem& mem, u32 instr) {
|
||||
@@ -305,7 +336,7 @@ void Interpreter::ldl(Mem& mem, u32 instr) {
|
||||
} else {
|
||||
s32 shift = 8 * ((address ^ 0) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, paddr & ~7);
|
||||
s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||
regs.gpr[RT(instr)] = result;
|
||||
}
|
||||
@@ -320,7 +351,7 @@ void Interpreter::ldr(Mem& mem, u32 instr) {
|
||||
} else {
|
||||
s32 shift = 8 * ((address ^ 7) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, paddr & ~7);
|
||||
s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||
regs.gpr[RT(instr)] = result;
|
||||
}
|
||||
@@ -328,91 +359,129 @@ void Interpreter::ldr(Mem& mem, u32 instr) {
|
||||
|
||||
void Interpreter::lbu(Mem& mem, u32 instr) {
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u8 value = mem.Read8(regs, address, regs.oldPC);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
u32 paddr;
|
||||
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
u8 value = mem.Read8(regs, paddr);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::lhu(Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b1)) {
|
||||
if ((address & 0b1) > 0) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u16 value = mem.Read16(regs, address, regs.oldPC);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
u32 paddr;
|
||||
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
u16 value = mem.Read16(regs, paddr);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::lwu(Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b11)) {
|
||||
if ((address & 0b11) > 0) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 value = mem.Read32(regs, address, regs.oldPC);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
u32 paddr;
|
||||
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||
} else {
|
||||
u32 value = mem.Read32(regs, paddr);
|
||||
regs.gpr[RT(instr)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::sb(Mem& mem, u32 instr) {
|
||||
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC);
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
u32 paddr;
|
||||
if (!MapVAddr(regs, STORE, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write8(regs, paddr, regs.gpr[RT(instr)]);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::sc(Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b11)) {
|
||||
HandleTLBException(regs, address);
|
||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
|
||||
if ((address & 0b11) > 0) {
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if(regs.cop0.llbit) {
|
||||
mem.Write32(regs, address, regs.gpr[RT(instr)], regs.oldPC);
|
||||
regs.cop0.llbit = false;
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, STORE, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write32(regs, paddr, regs.gpr[RT(instr)]);
|
||||
regs.gpr[RT(instr)] = 1;
|
||||
}
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = 0;
|
||||
}
|
||||
|
||||
regs.gpr[RT(instr)] = (u64)regs.cop0.llbit;
|
||||
regs.cop0.llbit = false;
|
||||
}
|
||||
|
||||
void Interpreter::scd(Mem& mem, u32 instr) {
|
||||
if (!regs.cop0.is_64bit_addressing && !regs.cop0.kernel_mode) {
|
||||
FireException(regs, ExceptionCode::ReservedInstruction, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b111)) {
|
||||
if ((address & 0b111) > 0) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if(regs.cop0.llbit) {
|
||||
mem.Write64(regs, address, regs.gpr[RT(instr)], regs.oldPC);
|
||||
regs.cop0.llbit = false;
|
||||
u32 paddr = 0;
|
||||
if(!MapVAddr(regs, STORE, address, paddr)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write32(regs, paddr, regs.gpr[RT(instr)]);
|
||||
regs.gpr[RT(instr)] = 1;
|
||||
}
|
||||
} else {
|
||||
regs.gpr[RT(instr)] = 0;
|
||||
}
|
||||
|
||||
regs.gpr[RT(instr)] = (s64)((u64)regs.cop0.llbit);
|
||||
regs.cop0.llbit = false;
|
||||
}
|
||||
|
||||
void Interpreter::sh(Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b1)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 physical;
|
||||
if(!MapVAddr(regs, STORE, address, physical)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write16<false>(regs, physical, regs.gpr[RT(instr)], regs.oldPC);
|
||||
mem.Write16(regs, physical, regs.gpr[RT(instr)]);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::sw(Mem& mem, u32 instr) {
|
||||
s16 offset = instr;
|
||||
u64 address = regs.gpr[RS(instr)] + offset;
|
||||
if (check_address_error(address, 0b11)) {
|
||||
if (check_address_error(0b11, address)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||
return;
|
||||
@@ -423,13 +492,13 @@ void Interpreter::sw(Mem& mem, u32 instr) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write32<false>(regs, physical, regs.gpr[RT(instr)], regs.oldPC);
|
||||
mem.Write32(regs, physical, regs.gpr[RT(instr)]);
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::sd(Mem& mem, u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||
if (check_address_error(address, 0b11)) {
|
||||
if (check_address_error(0b111, address)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||
return;
|
||||
@@ -440,9 +509,8 @@ void Interpreter::sd(Mem& mem, u32 instr) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||
} else {
|
||||
mem.Write64<false>(regs, physical, regs.gpr[RT(instr)], regs.oldPC);
|
||||
mem.Write64(regs, physical, regs.gpr[RT(instr)]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Interpreter::sdl(Mem& mem, u32 instr) {
|
||||
@@ -454,9 +522,9 @@ void Interpreter::sdl(Mem& mem, u32 instr) {
|
||||
} else {
|
||||
s32 shift = 8 * ((address ^ 0) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, paddr & ~7);
|
||||
u64 rt = regs.gpr[RT(instr)];
|
||||
mem.Write64<false>(regs, paddr & ~7, (data & ~mask) | (rt >> shift), regs.oldPC);
|
||||
mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt >> shift));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,9 +537,9 @@ void Interpreter::sdr(Mem& mem, u32 instr) {
|
||||
} else {
|
||||
s32 shift = 8 * ((address ^ 7) & 7);
|
||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
||||
u64 data = mem.Read64<false>(regs, paddr & ~7, regs.oldPC);
|
||||
u64 data = mem.Read64(regs, paddr & ~7);
|
||||
u64 rt = regs.gpr[RT(instr)];
|
||||
mem.Write64<false>(regs, paddr & ~7, (data & ~mask) | (rt << shift), regs.oldPC);
|
||||
mem.Write64(regs, paddr & ~7, (data & ~mask) | (rt << shift));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,9 +552,9 @@ void Interpreter::swl(Mem& mem, u32 instr) {
|
||||
} else {
|
||||
u32 shift = 8 * ((address ^ 0) & 3);
|
||||
u32 mask = 0xFFFFFFFF >> shift;
|
||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, paddr & ~3);
|
||||
u32 rt = regs.gpr[RT(instr)];
|
||||
mem.Write32<false>(regs, paddr & ~3, (data & ~mask) | (rt >> shift), regs.oldPC);
|
||||
mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt >> shift));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,9 +567,9 @@ void Interpreter::swr(Mem& mem, u32 instr) {
|
||||
} else {
|
||||
u32 shift = 8 * ((address ^ 3) & 3);
|
||||
u32 mask = 0xFFFFFFFF << shift;
|
||||
u32 data = mem.Read32<false>(regs, paddr & ~3, regs.oldPC);
|
||||
u32 data = mem.Read32(regs, paddr & ~3);
|
||||
u32 rt = regs.gpr[RT(instr)];
|
||||
mem.Write32<false>(regs, paddr & ~3, (data & ~mask) | (rt << shift), regs.oldPC);
|
||||
mem.Write32(regs, paddr & ~3, (data & ~mask) | (rt << shift));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,10 +590,6 @@ void Interpreter::nor(u32 instr) {
|
||||
void Interpreter::j(u32 instr) {
|
||||
s32 target = (instr & 0x3ffffff) << 2;
|
||||
s64 address = (regs.oldPC & ~0xfffffff) | target;
|
||||
if (check_address_error(address, 0b11)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::DataBusError, 0, true);
|
||||
}
|
||||
|
||||
branch(true, address);
|
||||
}
|
||||
@@ -679,11 +743,6 @@ void Interpreter::dsra32(u32 instr) {
|
||||
|
||||
void Interpreter::jr(u32 instr) {
|
||||
s64 address = regs.gpr[RS(instr)];
|
||||
if (check_address_error(address, 0b11)) {
|
||||
HandleTLBException(regs, address);
|
||||
FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC);
|
||||
}
|
||||
|
||||
branch(true, address);
|
||||
}
|
||||
|
||||
@@ -692,7 +751,7 @@ void Interpreter::dsub(u32 instr) {
|
||||
s64 rs = regs.gpr[RS(instr)];
|
||||
s64 result = rs - rt;
|
||||
if(check_signed_underflow(rs, rt, result)) {
|
||||
FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::Overflow, 0, true);
|
||||
} else {
|
||||
regs.gpr[RD(instr)] = result;
|
||||
}
|
||||
@@ -710,7 +769,7 @@ void Interpreter::sub(u32 instr) {
|
||||
s32 rs = regs.gpr[RS(instr)];
|
||||
s32 result = rs - rt;
|
||||
if(check_signed_underflow(rs, rt, result)) {
|
||||
FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::Overflow, 0, true);
|
||||
} else {
|
||||
regs.gpr[RD(instr)] = result;
|
||||
}
|
||||
@@ -773,7 +832,7 @@ void Interpreter::mthi(u32 instr) {
|
||||
|
||||
void Interpreter::trap(bool cond) {
|
||||
if(cond) {
|
||||
FireException(regs, ExceptionCode::Trap, 0, regs.oldPC);
|
||||
FireException(regs, ExceptionCode::Trap, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,11 +73,11 @@ void ProcessPIFCommands(u8* pifRam, Controller& controller, Mem& mem) {
|
||||
void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||
u32 cicType = cartInfo.cicType;
|
||||
bool pal = cartInfo.isPAL;
|
||||
mem.Write32<false>(regs, 0x1FC007E4, cicSeeds[cicType], regs.pc);
|
||||
mem.Write32(regs, 0x1FC007E4, cicSeeds[cicType]);
|
||||
|
||||
switch(cicType) {
|
||||
case CIC_NUS_6101:
|
||||
mem.Write32<false>(regs, 0x318, RDRAM_SIZE, regs.pc);
|
||||
mem.Write32(regs, 0x318, RDRAM_SIZE);
|
||||
regs.gpr[2] = (s64)0xFFFFFFFFDF6445CC;
|
||||
regs.gpr[3] = (s64)0xFFFFFFFFDF6445CC;
|
||||
regs.gpr[4] = 0x45CC;
|
||||
@@ -102,7 +102,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||
regs.hi = (s64)0xFFFFFFFF997EC317;
|
||||
break;
|
||||
case CIC_NUS_7102:
|
||||
mem.Write32<false>(regs, 0x318, RDRAM_SIZE, regs.pc);
|
||||
mem.Write32(regs, 0x318, RDRAM_SIZE);
|
||||
regs.gpr[1] = 0x0000000000000001;
|
||||
regs.gpr[2] = 0x000000001E324416;
|
||||
regs.gpr[3] = 0x000000001E324416;
|
||||
@@ -127,7 +127,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||
regs.hi = 0x0000000010054A98;
|
||||
break;
|
||||
case CIC_NUS_6102_7101:
|
||||
mem.Write32<false>(regs, 0x318, RDRAM_SIZE, regs.pc);
|
||||
mem.Write32(regs, 0x318, RDRAM_SIZE);
|
||||
regs.gpr[1] = 0x0000000000000001;
|
||||
regs.gpr[2] = 0x000000000EBDA536;
|
||||
regs.gpr[3] = 0x000000000EBDA536;
|
||||
@@ -157,7 +157,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||
}
|
||||
break;
|
||||
case CIC_NUS_6103_7103:
|
||||
mem.Write32<false>(regs, 0x318, RDRAM_SIZE, regs.pc);
|
||||
mem.Write32(regs, 0x318, RDRAM_SIZE);
|
||||
regs.gpr[0] = 0x0000000000000000;
|
||||
regs.gpr[1] = 0x0000000000000001;
|
||||
regs.gpr[2] = 0x0000000049A5EE96;
|
||||
@@ -200,7 +200,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||
}
|
||||
break;
|
||||
case CIC_NUS_6105_7105:
|
||||
mem.Write32<false>(regs, 0x3F0, RDRAM_SIZE, regs.pc);
|
||||
mem.Write32(regs, 0x3F0, RDRAM_SIZE);
|
||||
regs.gpr[2] = (s64)0xFFFFFFFFF58B0FBF;
|
||||
regs.gpr[3] = (s64)0xFFFFFFFFF58B0FBF;
|
||||
regs.gpr[4] = 0x0000000000000FBF;
|
||||
@@ -229,14 +229,14 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||
regs.gpr[31] = (s64)0xFFFFFFFFA4001554;
|
||||
}
|
||||
|
||||
mem.Write32<false>(regs, 0x04001000, 0x3C0DBFC0, regs.pc);
|
||||
mem.Write32<false>(regs, 0x04001004, 0x8DA807FC, regs.pc);
|
||||
mem.Write32<false>(regs, 0x04001008, 0x25AD07C0, regs.pc);
|
||||
mem.Write32<false>(regs, 0x0400100C, 0x31080080, regs.pc);
|
||||
mem.Write32<false>(regs, 0x04001000, 0x5500FFFC, regs.pc);
|
||||
mem.Write32<false>(regs, 0x04001004, 0x3C0DBFC0, regs.pc);
|
||||
mem.Write32<false>(regs, 0x04001008, 0x8DA80024, regs.pc);
|
||||
mem.Write32<false>(regs, 0x0400100C, 0x3C0BB000, regs.pc);
|
||||
mem.Write32(regs, 0x04001000, 0x3C0DBFC0);
|
||||
mem.Write32(regs, 0x04001004, 0x8DA807FC);
|
||||
mem.Write32(regs, 0x04001008, 0x25AD07C0);
|
||||
mem.Write32(regs, 0x0400100C, 0x31080080);
|
||||
mem.Write32(regs, 0x04001000, 0x5500FFFC);
|
||||
mem.Write32(regs, 0x04001004, 0x3C0DBFC0);
|
||||
mem.Write32(regs, 0x04001008, 0x8DA80024);
|
||||
mem.Write32(regs, 0x0400100C, 0x3C0BB000);
|
||||
break;
|
||||
case CIC_NUS_6106_7106:
|
||||
regs.gpr[2] = (s64)0xFFFFFFFFA95930A4;
|
||||
|
||||
@@ -327,9 +327,9 @@ void Cop0::decode(Registers& regs, Mem& mem, u32 instr) {
|
||||
case 0x05: dmtc0(regs, instr); break;
|
||||
case 0x10 ... 0x1F:
|
||||
switch(mask_cop2) {
|
||||
case 0x01: tlbr(regs); break;
|
||||
case 0x02: tlbw(index & 0x3F, regs); break;
|
||||
case 0x06: tlbw(GetRandom(), regs); break;
|
||||
case 0x01: tlbr(); break;
|
||||
case 0x02: tlbw(index & 0x3F); break;
|
||||
case 0x06: tlbw(GetRandom()); break;
|
||||
case 0x08: tlbp(regs); break;
|
||||
case 0x18: eret(regs); break;
|
||||
default: Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC);
|
||||
|
||||
@@ -260,8 +260,8 @@ private:
|
||||
void dmfc0(n64::Registers&, u32);
|
||||
void eret(n64::Registers&);
|
||||
|
||||
void tlbr(n64::Registers&);
|
||||
void tlbw(int, n64::Registers&);
|
||||
void tlbr();
|
||||
void tlbw(int);
|
||||
void tlbp(n64::Registers&);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user