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) {
|
while(!prevBranch) {
|
||||||
instrInBlock++;
|
instrInBlock++;
|
||||||
prevBranch = branch;
|
prevBranch = branch;
|
||||||
u32 instr = mem.Read32<false>(regs, loopPC, loopPC);
|
u32 instr = mem.Read32(regs, loopPC);
|
||||||
|
|
||||||
emitBreakpoint();
|
emitBreakpoint();
|
||||||
code.mov(rdi, (uintptr_t)®s);
|
code.mov(rdi, (uintptr_t)®s);
|
||||||
@@ -104,8 +104,11 @@ int Dynarec::Step(Mem &mem) {
|
|||||||
regs.delaySlot = false;
|
regs.delaySlot = false;
|
||||||
|
|
||||||
u32 pc{};
|
u32 pc{};
|
||||||
|
|
||||||
if(!MapVAddr(regs, LOAD, regs.pc, 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]) {
|
if(blockCache[pc >> 20]) {
|
||||||
|
|||||||
@@ -29,13 +29,20 @@ void Interpreter::Step(Mem& mem) {
|
|||||||
regs.prevDelaySlot = regs.delaySlot;
|
regs.prevDelaySlot = regs.delaySlot;
|
||||||
regs.delaySlot = false;
|
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)) {
|
if(ShouldServiceInterrupt(regs)) {
|
||||||
FireException(regs, ExceptionCode::Interrupt, 0, false);
|
FireException(regs, ExceptionCode::Interrupt, 0, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 instruction = mem.Read32(regs, regs.pc, regs.pc);
|
|
||||||
|
|
||||||
regs.oldPC = regs.pc;
|
regs.oldPC = regs.pc;
|
||||||
regs.pc = regs.nextPC;
|
regs.pc = regs.nextPC;
|
||||||
regs.nextPC += 4;
|
regs.nextPC += 4;
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ void Mem::Reset() {
|
|||||||
std::fill(readPages.begin(), readPages.end(), 0);
|
std::fill(readPages.begin(), readPages.end(), 0);
|
||||||
std::fill(writePages.begin(), writePages.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 addr = (i * PAGE_SIZE) & RDRAM_DSIZE;
|
||||||
const auto pointer = (uintptr_t) &mmio.rdp.rdram[addr];
|
const auto pointer = (uintptr_t) &mmio.rdp.rdram[addr];
|
||||||
readPages[i] = pointer;
|
readPages[i] = pointer;
|
||||||
@@ -66,6 +67,12 @@ CartInfo Mem::LoadROM(const std::string& filename) {
|
|||||||
SetCICType(result.cicType, cicChecksum);
|
SetCICType(result.cicType, cicChecksum);
|
||||||
result.isPAL = IsROMPAL();
|
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;
|
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<true>(Registers& regs, TLBAccessType accessType, u64 vaddr, u32& paddr);
|
||||||
template bool MapVAddr<false>(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, u32 paddr) {
|
||||||
u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) {
|
if(paddr >= 0x10000000 && paddr <= 0x1FBFFFFF)
|
||||||
u32 paddr = vaddr;
|
paddr = (paddr + 2) & ~2;
|
||||||
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
|
|
||||||
HandleTLBException(regs, vaddr);
|
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
const auto offset = paddr & 0xFFF;
|
const auto offset = paddr & 0xFFF;
|
||||||
@@ -123,7 +126,6 @@ u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) {
|
|||||||
return (w >> (offs * 8)) & 0xff;
|
return (w >> (offs * 8)) & 0xff;
|
||||||
}
|
}
|
||||||
case 0x10000000 ... 0x1FBFFFFF:
|
case 0x10000000 ... 0x1FBFFFFF:
|
||||||
paddr = (paddr + 2) & ~2;
|
|
||||||
return cart[BYTE_ADDRESS(paddr) & romMask];
|
return cart[BYTE_ADDRESS(paddr) & romMask];
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return pifBootrom[BYTE_ADDRESS(paddr) - 0x1FC00000];
|
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, u32 paddr) {
|
||||||
u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) {
|
if(paddr >= 0x10000000 && paddr <= 0x1FBFFFFF)
|
||||||
u32 paddr = vaddr;
|
paddr = (paddr + 2) & ~3;
|
||||||
if (!MapVAddr<tlb>(regs, LOAD, vaddr, paddr)) {
|
|
||||||
HandleTLBException(regs, vaddr);
|
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
const auto offset = paddr & 0xFFF;
|
const auto offset = paddr & 0xFFF;
|
||||||
@@ -169,7 +167,6 @@ u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) {
|
|||||||
case 0x04500000 ... 0x048FFFFF:
|
case 0x04500000 ... 0x048FFFFF:
|
||||||
return mmio.Read(paddr);
|
return mmio.Read(paddr);
|
||||||
case 0x10000000 ... 0x1FBFFFFF:
|
case 0x10000000 ... 0x1FBFFFFF:
|
||||||
paddr = (paddr + 2) & ~3;
|
|
||||||
return Util::ReadAccess<u16>(cart.data(), HALF_ADDRESS(paddr) & romMask);
|
return Util::ReadAccess<u16>(cart.data(), HALF_ADDRESS(paddr) & romMask);
|
||||||
case 0x1FC00000 ... 0x1FC007BF:
|
case 0x1FC00000 ... 0x1FC007BF:
|
||||||
return Util::ReadAccess<u16>(pifBootrom, HALF_ADDRESS(paddr) - 0x1FC00000);
|
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, u32 paddr) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
const auto offset = paddr & 0xFFF;
|
const auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
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, u32 paddr) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
const auto offset = paddr & 0xFFF;
|
const auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
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);
|
void Mem::Write8(Registers& regs, n64::JIT::Dynarec& dyn, u32 paddr, u32 val) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
dyn.InvalidatePage(BYTE_ADDRESS(paddr));
|
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;
|
const auto page = paddr >> 12;
|
||||||
auto offset = paddr & 0xFFF;
|
auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
|
||||||
val = val << (8 * (3 - (paddr & 3)));
|
|
||||||
offset = (offset & DMEM_DSIZE) & ~3;
|
|
||||||
}
|
|
||||||
|
|
||||||
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
|
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
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;
|
mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val;
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
val = val << (8 * (3 - (paddr & 3)));
|
|
||||||
paddr = (paddr & DMEM_DSIZE) & ~3;
|
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
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, u32 paddr, u32 val) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
dyn.InvalidatePage(HALF_ADDRESS(paddr));
|
dyn.InvalidatePage(HALF_ADDRESS(paddr));
|
||||||
|
|
||||||
|
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||||
|
val = val << (16 * !(paddr & 2));
|
||||||
|
paddr &= ~3;
|
||||||
|
}
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
auto offset = paddr & 0xFFF;
|
auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
|
||||||
val = val << (16 * !(paddr & 2));
|
|
||||||
offset &= ~3;
|
|
||||||
}
|
|
||||||
|
|
||||||
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
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);
|
Util::WriteAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val);
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
val = val << (16 * !(paddr & 2));
|
|
||||||
paddr &= ~3;
|
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
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, u32 paddr, u32 val) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
dyn.InvalidatePage(paddr);
|
dyn.InvalidatePage(paddr);
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
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, u32 paddr, u64 val) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
dyn.InvalidatePage(paddr);
|
dyn.InvalidatePage(paddr);
|
||||||
|
|
||||||
|
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||||
|
val >>= 32;
|
||||||
|
}
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
auto offset = paddr & 0xFFF;
|
auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
|
||||||
val >>= 32;
|
|
||||||
}
|
|
||||||
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
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);
|
Util::WriteAccess<u64>(mmio.rdp.rdram.data(), paddr, val);
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
val >>= 32;
|
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
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);
|
void Mem::Write8(Registers& regs, u32 paddr, u32 val) {
|
||||||
template void Mem::Write8<true>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||||
template void Mem::Write16<false>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
val = val << (8 * (3 - (paddr & 3)));
|
||||||
template void Mem::Write16<true>(Registers& regs, JIT::Dynarec&, u64 vaddr, u32 val, s64 pc);
|
paddr = (paddr & DMEM_DSIZE) & ~3;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
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];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
|
||||||
val = val << (8 * (3 - (paddr & 3)));
|
|
||||||
offset = (offset & DMEM_DSIZE) & ~3;
|
|
||||||
}
|
|
||||||
|
|
||||||
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
|
((u8*)pointer)[BYTE_ADDRESS(offset)] = val;
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
switch (paddr) {
|
||||||
@@ -545,8 +471,6 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val;
|
mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val;
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
val = val << (8 * (3 - (paddr & 3)));
|
|
||||||
paddr = (paddr & DMEM_DSIZE) & ~3;
|
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
else
|
||||||
@@ -579,12 +503,10 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool tlb>
|
void Mem::Write16(Registers& regs, u32 paddr, u32 val) {
|
||||||
void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||||
u32 paddr = vaddr;
|
val = val << (16 * !(paddr & 2));
|
||||||
if (!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
|
paddr &= ~3;
|
||||||
HandleTLBException(regs, vaddr);
|
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
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];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
|
||||||
val = val << (16 * !(paddr & 2));
|
|
||||||
offset &= ~3;
|
|
||||||
}
|
|
||||||
|
|
||||||
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
Util::WriteAccess<u16>((u8*)pointer, HALF_ADDRESS(offset), val);
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
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);
|
Util::WriteAccess<u16>(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val);
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
val = val << (16 * !(paddr & 2));
|
|
||||||
paddr &= ~3;
|
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
else
|
||||||
@@ -638,14 +553,7 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool tlb>
|
void Mem::Write32(Registers& regs, u32 paddr, u32 val) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
const auto page = paddr >> 12;
|
||||||
auto offset = paddr & 0xFFF;
|
auto offset = paddr & 0xFFF;
|
||||||
const auto pointer = readPages[page];
|
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, u32 paddr, u64 val) {
|
||||||
void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
|
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
||||||
u32 paddr = vaddr;
|
val >>= 32;
|
||||||
if(!MapVAddr<tlb>(regs, STORE, vaddr, paddr)) {
|
|
||||||
HandleTLBException(regs, vaddr);
|
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto page = paddr >> 12;
|
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];
|
const auto pointer = readPages[page];
|
||||||
|
|
||||||
if(pointer) {
|
if(pointer) {
|
||||||
if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) {
|
|
||||||
val >>= 32;
|
|
||||||
}
|
|
||||||
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
Util::WriteAccess<u64>((u8*)pointer, offset, val);
|
||||||
} else {
|
} else {
|
||||||
switch (paddr) {
|
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);
|
Util::WriteAccess<u64>(mmio.rdp.rdram.data(), paddr, val);
|
||||||
break;
|
break;
|
||||||
case 0x04000000 ... 0x0403FFFF:
|
case 0x04000000 ... 0x0403FFFF:
|
||||||
val >>= 32;
|
|
||||||
if (paddr & 0x1000)
|
if (paddr & 0x1000)
|
||||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||||
else
|
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();
|
return mmio.rdp.rdram.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool tlb = true>
|
u8 Read8(Registers&, u32);
|
||||||
u8 Read8(Registers&, u64, s64);
|
u16 Read16(Registers&, u32);
|
||||||
template <bool tlb = true>
|
u32 Read32(Registers&, u32);
|
||||||
u16 Read16(Registers&, u64, s64);
|
u64 Read64(Registers&, u32);
|
||||||
template <bool tlb = true>
|
void Write8(Registers&, JIT::Dynarec&, u32, u32);
|
||||||
u32 Read32(Registers&, u64, s64);
|
void Write16(Registers&, JIT::Dynarec&, u32, u32);
|
||||||
template <bool tlb = true>
|
void Write32(Registers&, JIT::Dynarec&, u32, u32);
|
||||||
u64 Read64(Registers&, u64, s64);
|
void Write64(Registers&, JIT::Dynarec&, u32, u64);
|
||||||
template <bool tlb = true>
|
void Write8(Registers&, u32, u32);
|
||||||
void Write8(Registers&, JIT::Dynarec&, u64, u32, s64);
|
void Write16(Registers&, u32, u32);
|
||||||
template <bool tlb = true>
|
void Write32(Registers&, u32, u32);
|
||||||
void Write16(Registers&, JIT::Dynarec&, u64, u32, s64);
|
void Write64(Registers&, u32, u64);
|
||||||
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);
|
|
||||||
|
|
||||||
MMIO mmio;
|
MMIO mmio;
|
||||||
u8 pifRam[PIF_RAM_SIZE]{};
|
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)];
|
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||||
if(addr & 3) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
||||||
HandleTLBException(regs, addr);
|
HandleTLBException(regs, addr);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} 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);
|
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)];
|
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||||
if(addr & 3) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, STORE, addr, physical)) {
|
if(!MapVAddr(regs, STORE, addr, physical)) {
|
||||||
HandleTLBException(regs, addr);
|
HandleTLBException(regs, addr);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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) {
|
void ldc1(n64::Registers& regs, Mem& mem, u32 instr) {
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||||
if(addr & 7) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, regs.oldPC);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
||||||
HandleTLBException(regs, addr);
|
HandleTLBException(regs, addr);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} 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);
|
regs.cop1.SetReg<u64>(regs.cop0, FT(instr), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdc1(n64::Registers& regs, Mem& mem, u32 instr) {
|
void sdc1(n64::Registers& regs, Mem& mem, u32 instr) {
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||||
if(addr & 7) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, STORE, addr, physical)) {
|
if(!MapVAddr(regs, STORE, addr, physical)) {
|
||||||
HandleTLBException(regs, addr);
|
HandleTLBException(regs, addr);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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 <core/Dynarec.hpp>
|
||||||
#include <Registers.hpp>
|
|
||||||
|
|
||||||
#define se_imm(x) ((s16)((x) & 0xFFFF))
|
#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, 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);
|
s16 imm = (s16)(instr);
|
||||||
s32 result = rs + imm;
|
s32 result = rs + imm;
|
||||||
regs.gpr[RT(instr)] = result;
|
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) {
|
void dadd(Registers& regs, u32 instr) {
|
||||||
@@ -147,7 +145,6 @@ void ddivu(Registers& regs, u32 instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void branch(Registers& regs, bool cond, s64 address) {
|
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;
|
regs.delaySlot = true;
|
||||||
if (cond) {
|
if (cond) {
|
||||||
regs.nextPC = address;
|
regs.nextPC = address;
|
||||||
@@ -157,10 +154,8 @@ void branch(Registers& regs, bool cond, s64 address) {
|
|||||||
void branch_likely(Registers& regs, bool cond, s64 address) {
|
void branch_likely(Registers& regs, bool cond, s64 address) {
|
||||||
regs.delaySlot = true;
|
regs.delaySlot = true;
|
||||||
if (cond) {
|
if (cond) {
|
||||||
//Util::debug("\t\tJIT branch likely taken from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address);
|
|
||||||
regs.nextPC = address;
|
regs.nextPC = address;
|
||||||
} else {
|
} else {
|
||||||
//Util::debug("\t\tJIT branch likely not taken from {:08X} -> {:08X}\n", (u32)regs.oldPC, (u32)address);
|
|
||||||
regs.SetPC(regs.nextPC);
|
regs.SetPC(regs.nextPC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,18 +194,30 @@ void lui(Registers& regs, u32 instr) {
|
|||||||
|
|
||||||
void lb(Registers& regs, Mem& mem, u32 instr) {
|
void lb(Registers& regs, Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)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) {
|
void lh(Registers& regs, Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b1)) {
|
if ((address & 0b1) > 0) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||||
return;
|
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) {
|
void lw(Registers& regs, Mem& mem, u32 instr) {
|
||||||
@@ -222,23 +229,28 @@ void lw(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 physical;
|
u32 physical = 0;
|
||||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} 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) {
|
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;
|
u32 physical;
|
||||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} 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;
|
regs.cop0.llbit = true;
|
||||||
@@ -254,7 +266,7 @@ void lwl(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
u32 shift = 8 * ((address ^ 0) & 3);
|
u32 shift = 8 * ((address ^ 0) & 3);
|
||||||
u32 mask = 0xFFFFFFFF << shift;
|
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));
|
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -269,7 +281,7 @@ void lwr(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
u32 shift = 8 * ((address ^ 3) & 3);
|
u32 shift = 8 * ((address ^ 3) & 3);
|
||||||
u32 mask = 0xFFFFFFFF >> shift;
|
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));
|
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -283,22 +295,30 @@ void ld(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 value = mem.Read64(regs, address, regs.oldPC);
|
s64 value = mem.Read64(regs, address);
|
||||||
regs.gpr[RT(instr)] = value;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lld(Registers& regs, Mem& mem, u32 instr) {
|
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;
|
u32 paddr;
|
||||||
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} 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) {
|
void ldl(Registers& regs, Mem& mem, u32 instr) {
|
||||||
@@ -310,7 +330,7 @@ void ldl(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
s32 shift = 8 * ((address ^ 0) & 7);
|
s32 shift = 8 * ((address ^ 0) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
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));
|
s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -325,7 +345,7 @@ void ldr(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
s32 shift = 8 * ((address ^ 7) & 7);
|
s32 shift = 8 * ((address ^ 7) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
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));
|
s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
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) {
|
void lbu(Registers& regs, Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)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;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +365,7 @@ void lhu(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 value = mem.Read16(regs, address, regs.oldPC);
|
u16 value = mem.Read16(regs, address);
|
||||||
regs.gpr[RT(instr)] = value;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,28 +377,36 @@ void lwu(Registers& regs, Mem& mem, u32 instr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 value = mem.Read32(regs, address, regs.oldPC);
|
u32 value = mem.Read32(regs, address);
|
||||||
regs.gpr[RT(instr)] = value;
|
regs.gpr[RT(instr)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sb(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
void sb(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||||
u32 address = regs.gpr[RS(instr)] + (s16)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) {
|
void sc(Registers& regs, Mem& mem, Dynarec& dyn, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b11)) {
|
|
||||||
HandleTLBException(regs, address);
|
if ((address & 0b11) > 0) {
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.cop0.llbit) {
|
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) {
|
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) {
|
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);
|
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);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
s32 shift = 8 * ((address ^ 0) & 7);
|
s32 shift = 8 * ((address ^ 0) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
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)];
|
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 {
|
} else {
|
||||||
s32 shift = 8 * ((address ^ 7) & 7);
|
s32 shift = 8 * ((address ^ 7) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
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)];
|
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 {
|
} else {
|
||||||
u32 shift = 8 * ((address ^ 0) & 3);
|
u32 shift = 8 * ((address ^ 0) & 3);
|
||||||
u32 mask = 0xFFFFFFFF >> shift;
|
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)];
|
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 {
|
} else {
|
||||||
u32 shift = 8 * ((address ^ 3) & 3);
|
u32 shift = 8 * ((address ^ 3) & 3);
|
||||||
u32 mask = 0xFFFFFFFF << shift;
|
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)];
|
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) {
|
void j(Registers& regs, u32 instr) {
|
||||||
s32 target = (instr & 0x3ffffff) << 2;
|
u64 target = (instr & 0x3ffffff) << 2;
|
||||||
s64 address = (regs.oldPC & ~0xfffffff) | target;
|
u64 address = ((regs.pc - 4) & ~0xfffffff) | target;
|
||||||
if (check_address_error(address, 0b11)) {
|
|
||||||
HandleTLBException(regs, address);
|
|
||||||
FireException(regs, ExceptionCode::DataBusError, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
branch(regs, true, address);
|
branch(regs, true, address);
|
||||||
}
|
}
|
||||||
@@ -686,7 +710,7 @@ void jr(Registers& regs, u32 instr) {
|
|||||||
s64 address = regs.gpr[RS(instr)];
|
s64 address = regs.gpr[RS(instr)];
|
||||||
if (check_address_error(address, 0b11)) {
|
if (check_address_error(address, 0b11)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::DataBusError, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::DataBusError, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
branch(regs, true, address);
|
branch(regs, true, address);
|
||||||
@@ -697,7 +721,7 @@ void dsub(Registers& regs, u32 instr) {
|
|||||||
s64 rs = regs.gpr[RS(instr)];
|
s64 rs = regs.gpr[RS(instr)];
|
||||||
s64 result = rs - rt;
|
s64 result = rs - rt;
|
||||||
if(check_signed_underflow(rs, rt, result)) {
|
if(check_signed_underflow(rs, rt, result)) {
|
||||||
FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::Overflow, 0, true);
|
||||||
} else {
|
} else {
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -715,7 +739,7 @@ void sub(Registers& regs, u32 instr) {
|
|||||||
s32 rs = regs.gpr[RS(instr)];
|
s32 rs = regs.gpr[RS(instr)];
|
||||||
s32 result = rs - rt;
|
s32 result = rs - rt;
|
||||||
if(check_signed_underflow(rs, rt, result)) {
|
if(check_signed_underflow(rs, rt, result)) {
|
||||||
FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::Overflow, 0, true);
|
||||||
} else {
|
} else {
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -778,7 +802,7 @@ void mthi(Registers& regs, u32 instr) {
|
|||||||
|
|
||||||
void trap(Registers& regs, bool cond) {
|
void trap(Registers& regs, bool cond) {
|
||||||
if(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) {
|
void dmfc2(Dynarec& dyn, Registers& regs, u32 instr) {
|
||||||
regs.gpr[RT(instr)] = dyn.cop2Latch;
|
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;
|
u8 Index = index & 0b111111;
|
||||||
if (Index >= 32) {
|
if (Index >= 32) {
|
||||||
Util::panic("TLBR with TLB index {}", index);
|
Util::panic("TLBR with TLB index {}", index);
|
||||||
@@ -48,7 +48,7 @@ void Cop0::tlbr(Registers& regs) {
|
|||||||
pageMask.raw = entry.pageMask.raw;
|
pageMask.raw = entry.pageMask.raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop0::tlbw(int index_, Registers& regs) {
|
void Cop0::tlbw(int index_) {
|
||||||
PageMask page_mask{};
|
PageMask page_mask{};
|
||||||
page_mask = pageMask;
|
page_mask = pageMask;
|
||||||
u32 top = page_mask.mask & 0xAAA;
|
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)];
|
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||||
if(addr & 3) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
||||||
HandleTLBException(regs, addr);
|
HandleTLBException(regs, addr);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} else {
|
||||||
u32 data = mem.Read32<false>(regs, physical, regs.oldPC);
|
u32 data = mem.Read32(regs, physical);
|
||||||
SetReg<u32>(regs.cop0, FT(instr), data);
|
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)];
|
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||||
if(addr & 3) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, STORE, addr, physical)) {
|
if(!MapVAddr(regs, STORE, addr, physical)) {
|
||||||
HandleTLBException(regs, addr);
|
HandleTLBException(regs, addr);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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)];
|
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||||
if(addr & 7) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
if(!MapVAddr(regs, LOAD, addr, physical)) {
|
||||||
HandleTLBException(regs, addr);
|
HandleTLBException(regs, addr);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, regs.oldPC);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} else {
|
||||||
u64 data = mem.Read64<false>(regs, physical, regs.oldPC);
|
u64 data = mem.Read64(regs, physical);
|
||||||
SetReg<u64>(regs.cop0, FT(instr), data);
|
SetReg<u64>(regs.cop0, FT(instr), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::sdc1(Registers& regs, Mem& mem, u32 instr) {
|
void Cop1::sdc1(Registers& regs, Mem& mem, u32 instr) {
|
||||||
if(!regs.cop0.status.cu1) {
|
if(!regs.cop0.status.cu1) {
|
||||||
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, regs.oldPC);
|
FireException(regs, ExceptionCode::CoprocessorUnusable, 1, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
u64 addr = (s64)(s16)instr + regs.gpr[BASE(instr)];
|
||||||
if(addr & 7) {
|
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, regs.oldPC);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 physical;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, STORE, addr, physical)) {
|
if(!MapVAddr(regs, STORE, addr, physical)) {
|
||||||
HandleTLBException(regs, addr);
|
HandleTLBException(regs, addr);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, regs.oldPC);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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>
|
#include <core/Interpreter.hpp>
|
||||||
|
|
||||||
#define se_imm(x) ((s16)((x) & 0xFFFF))
|
#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_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)
|
#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) {
|
void Interpreter::lb(Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)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) {
|
void Interpreter::lh(Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b1)) {
|
if ((address & 0b1) > 0) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||||
return;
|
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) {
|
void Interpreter::lw(Mem& mem, u32 instr) {
|
||||||
s16 offset = instr;
|
s16 offset = instr;
|
||||||
u64 address = regs.gpr[RS(instr)] + offset;
|
u64 address = regs.gpr[RS(instr)] + offset;
|
||||||
if (check_address_error(address, 0b11)) {
|
if (check_address_error(0b11, address)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 physical;
|
u32 physical = 0;
|
||||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} 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) {
|
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;
|
u32 physical;
|
||||||
if (!MapVAddr(regs, LOAD, address, physical)) {
|
if (!MapVAddr(regs, LOAD, address, physical)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} 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;
|
regs.cop0.llbit = true;
|
||||||
@@ -249,7 +266,7 @@ void Interpreter::lwl(Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
u32 shift = 8 * ((address ^ 0) & 3);
|
u32 shift = 8 * ((address ^ 0) & 3);
|
||||||
u32 mask = 0xFFFFFFFF << shift;
|
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));
|
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -264,7 +281,7 @@ void Interpreter::lwr(Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
u32 shift = 8 * ((address ^ 3) & 3);
|
u32 shift = 8 * ((address ^ 3) & 3);
|
||||||
u32 mask = 0xFFFFFFFF >> shift;
|
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));
|
s32 result = s32((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -272,28 +289,42 @@ void Interpreter::lwr(Mem& mem, u32 instr) {
|
|||||||
|
|
||||||
void Interpreter::ld(Mem& mem, u32 instr) {
|
void Interpreter::ld(Mem& mem, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b111)) {
|
if (check_address_error(0b111, address)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 value = mem.Read64(regs, address, regs.oldPC);
|
u32 paddr = 0;
|
||||||
regs.gpr[RT(instr)] = value;
|
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) {
|
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;
|
u32 paddr;
|
||||||
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, true);
|
||||||
} else {
|
} 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) {
|
void Interpreter::ldl(Mem& mem, u32 instr) {
|
||||||
@@ -305,7 +336,7 @@ void Interpreter::ldl(Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
s32 shift = 8 * ((address ^ 0) & 7);
|
s32 shift = 8 * ((address ^ 0) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
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));
|
s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data << shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -320,7 +351,7 @@ void Interpreter::ldr(Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
s32 shift = 8 * ((address ^ 7) & 7);
|
s32 shift = 8 * ((address ^ 7) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
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));
|
s64 result = (s64) ((regs.gpr[RT(instr)] & ~mask) | (data >> shift));
|
||||||
regs.gpr[RT(instr)] = result;
|
regs.gpr[RT(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -328,91 +359,129 @@ void Interpreter::ldr(Mem& mem, u32 instr) {
|
|||||||
|
|
||||||
void Interpreter::lbu(Mem& mem, u32 instr) {
|
void Interpreter::lbu(Mem& mem, u32 instr) {
|
||||||
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
u8 value = mem.Read8(regs, address, regs.oldPC);
|
u32 paddr;
|
||||||
regs.gpr[RT(instr)] = value;
|
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) {
|
void Interpreter::lhu(Mem& mem, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b1)) {
|
if ((address & 0b1) > 0) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
u32 paddr;
|
||||||
u16 value = mem.Read16(regs, address, regs.oldPC);
|
if (!MapVAddr(regs, LOAD, address, paddr)) {
|
||||||
regs.gpr[RT(instr)] = value;
|
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) {
|
void Interpreter::lwu(Mem& mem, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b11)) {
|
if ((address & 0b11) > 0) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorLoad, 0, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 value = mem.Read32(regs, address, regs.oldPC);
|
u32 paddr;
|
||||||
regs.gpr[RT(instr)] = value;
|
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) {
|
void Interpreter::sb(Mem& mem, u32 instr) {
|
||||||
u32 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
mem.Write8(regs, address, regs.gpr[RT(instr)], regs.oldPC);
|
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) {
|
void Interpreter::sc(Mem& mem, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
u64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b11)) {
|
|
||||||
HandleTLBException(regs, address);
|
if ((address & 0b11) > 0) {
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.cop0.llbit) {
|
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) {
|
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;
|
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b111)) {
|
if ((address & 0b111) > 0) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(regs.cop0.llbit) {
|
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) {
|
void Interpreter::sh(Mem& mem, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)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;
|
u32 physical;
|
||||||
if(!MapVAddr(regs, STORE, address, physical)) {
|
if(!MapVAddr(regs, STORE, address, physical)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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) {
|
void Interpreter::sw(Mem& mem, u32 instr) {
|
||||||
s16 offset = instr;
|
s16 offset = instr;
|
||||||
u64 address = regs.gpr[RS(instr)] + offset;
|
u64 address = regs.gpr[RS(instr)] + offset;
|
||||||
if (check_address_error(address, 0b11)) {
|
if (check_address_error(0b11, address)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||||
return;
|
return;
|
||||||
@@ -423,13 +492,13 @@ void Interpreter::sw(Mem& mem, u32 instr) {
|
|||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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) {
|
void Interpreter::sd(Mem& mem, u32 instr) {
|
||||||
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
s64 address = regs.gpr[RS(instr)] + (s16)instr;
|
||||||
if (check_address_error(address, 0b11)) {
|
if (check_address_error(0b111, address)) {
|
||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
FireException(regs, ExceptionCode::AddressErrorStore, 0, true);
|
||||||
return;
|
return;
|
||||||
@@ -440,9 +509,8 @@ void Interpreter::sd(Mem& mem, u32 instr) {
|
|||||||
HandleTLBException(regs, address);
|
HandleTLBException(regs, address);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, true);
|
||||||
} else {
|
} 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) {
|
void Interpreter::sdl(Mem& mem, u32 instr) {
|
||||||
@@ -454,9 +522,9 @@ void Interpreter::sdl(Mem& mem, u32 instr) {
|
|||||||
} else {
|
} else {
|
||||||
s32 shift = 8 * ((address ^ 0) & 7);
|
s32 shift = 8 * ((address ^ 0) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF >> shift;
|
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)];
|
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 {
|
} else {
|
||||||
s32 shift = 8 * ((address ^ 7) & 7);
|
s32 shift = 8 * ((address ^ 7) & 7);
|
||||||
u64 mask = 0xFFFFFFFFFFFFFFFF << shift;
|
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)];
|
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 {
|
} else {
|
||||||
u32 shift = 8 * ((address ^ 0) & 3);
|
u32 shift = 8 * ((address ^ 0) & 3);
|
||||||
u32 mask = 0xFFFFFFFF >> shift;
|
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)];
|
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 {
|
} else {
|
||||||
u32 shift = 8 * ((address ^ 3) & 3);
|
u32 shift = 8 * ((address ^ 3) & 3);
|
||||||
u32 mask = 0xFFFFFFFF << shift;
|
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)];
|
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) {
|
void Interpreter::j(u32 instr) {
|
||||||
s32 target = (instr & 0x3ffffff) << 2;
|
s32 target = (instr & 0x3ffffff) << 2;
|
||||||
s64 address = (regs.oldPC & ~0xfffffff) | target;
|
s64 address = (regs.oldPC & ~0xfffffff) | target;
|
||||||
if (check_address_error(address, 0b11)) {
|
|
||||||
HandleTLBException(regs, address);
|
|
||||||
FireException(regs, ExceptionCode::DataBusError, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
branch(true, address);
|
branch(true, address);
|
||||||
}
|
}
|
||||||
@@ -679,11 +743,6 @@ void Interpreter::dsra32(u32 instr) {
|
|||||||
|
|
||||||
void Interpreter::jr(u32 instr) {
|
void Interpreter::jr(u32 instr) {
|
||||||
s64 address = regs.gpr[RS(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);
|
branch(true, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,7 +751,7 @@ void Interpreter::dsub(u32 instr) {
|
|||||||
s64 rs = regs.gpr[RS(instr)];
|
s64 rs = regs.gpr[RS(instr)];
|
||||||
s64 result = rs - rt;
|
s64 result = rs - rt;
|
||||||
if(check_signed_underflow(rs, rt, result)) {
|
if(check_signed_underflow(rs, rt, result)) {
|
||||||
FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::Overflow, 0, true);
|
||||||
} else {
|
} else {
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -710,7 +769,7 @@ void Interpreter::sub(u32 instr) {
|
|||||||
s32 rs = regs.gpr[RS(instr)];
|
s32 rs = regs.gpr[RS(instr)];
|
||||||
s32 result = rs - rt;
|
s32 result = rs - rt;
|
||||||
if(check_signed_underflow(rs, rt, result)) {
|
if(check_signed_underflow(rs, rt, result)) {
|
||||||
FireException(regs, ExceptionCode::Overflow, 0, regs.oldPC);
|
FireException(regs, ExceptionCode::Overflow, 0, true);
|
||||||
} else {
|
} else {
|
||||||
regs.gpr[RD(instr)] = result;
|
regs.gpr[RD(instr)] = result;
|
||||||
}
|
}
|
||||||
@@ -773,7 +832,7 @@ void Interpreter::mthi(u32 instr) {
|
|||||||
|
|
||||||
void Interpreter::trap(bool cond) {
|
void Interpreter::trap(bool cond) {
|
||||||
if(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) {
|
void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
||||||
u32 cicType = cartInfo.cicType;
|
u32 cicType = cartInfo.cicType;
|
||||||
bool pal = cartInfo.isPAL;
|
bool pal = cartInfo.isPAL;
|
||||||
mem.Write32<false>(regs, 0x1FC007E4, cicSeeds[cicType], regs.pc);
|
mem.Write32(regs, 0x1FC007E4, cicSeeds[cicType]);
|
||||||
|
|
||||||
switch(cicType) {
|
switch(cicType) {
|
||||||
case CIC_NUS_6101:
|
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[2] = (s64)0xFFFFFFFFDF6445CC;
|
||||||
regs.gpr[3] = (s64)0xFFFFFFFFDF6445CC;
|
regs.gpr[3] = (s64)0xFFFFFFFFDF6445CC;
|
||||||
regs.gpr[4] = 0x45CC;
|
regs.gpr[4] = 0x45CC;
|
||||||
@@ -102,7 +102,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
|||||||
regs.hi = (s64)0xFFFFFFFF997EC317;
|
regs.hi = (s64)0xFFFFFFFF997EC317;
|
||||||
break;
|
break;
|
||||||
case CIC_NUS_7102:
|
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[1] = 0x0000000000000001;
|
||||||
regs.gpr[2] = 0x000000001E324416;
|
regs.gpr[2] = 0x000000001E324416;
|
||||||
regs.gpr[3] = 0x000000001E324416;
|
regs.gpr[3] = 0x000000001E324416;
|
||||||
@@ -127,7 +127,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
|||||||
regs.hi = 0x0000000010054A98;
|
regs.hi = 0x0000000010054A98;
|
||||||
break;
|
break;
|
||||||
case CIC_NUS_6102_7101:
|
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[1] = 0x0000000000000001;
|
||||||
regs.gpr[2] = 0x000000000EBDA536;
|
regs.gpr[2] = 0x000000000EBDA536;
|
||||||
regs.gpr[3] = 0x000000000EBDA536;
|
regs.gpr[3] = 0x000000000EBDA536;
|
||||||
@@ -157,7 +157,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CIC_NUS_6103_7103:
|
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[0] = 0x0000000000000000;
|
||||||
regs.gpr[1] = 0x0000000000000001;
|
regs.gpr[1] = 0x0000000000000001;
|
||||||
regs.gpr[2] = 0x0000000049A5EE96;
|
regs.gpr[2] = 0x0000000049A5EE96;
|
||||||
@@ -200,7 +200,7 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CIC_NUS_6105_7105:
|
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[2] = (s64)0xFFFFFFFFF58B0FBF;
|
||||||
regs.gpr[3] = (s64)0xFFFFFFFFF58B0FBF;
|
regs.gpr[3] = (s64)0xFFFFFFFFF58B0FBF;
|
||||||
regs.gpr[4] = 0x0000000000000FBF;
|
regs.gpr[4] = 0x0000000000000FBF;
|
||||||
@@ -229,14 +229,14 @@ void DoPIFHLE(Mem& mem, Registers& regs, CartInfo cartInfo) {
|
|||||||
regs.gpr[31] = (s64)0xFFFFFFFFA4001554;
|
regs.gpr[31] = (s64)0xFFFFFFFFA4001554;
|
||||||
}
|
}
|
||||||
|
|
||||||
mem.Write32<false>(regs, 0x04001000, 0x3C0DBFC0, regs.pc);
|
mem.Write32(regs, 0x04001000, 0x3C0DBFC0);
|
||||||
mem.Write32<false>(regs, 0x04001004, 0x8DA807FC, regs.pc);
|
mem.Write32(regs, 0x04001004, 0x8DA807FC);
|
||||||
mem.Write32<false>(regs, 0x04001008, 0x25AD07C0, regs.pc);
|
mem.Write32(regs, 0x04001008, 0x25AD07C0);
|
||||||
mem.Write32<false>(regs, 0x0400100C, 0x31080080, regs.pc);
|
mem.Write32(regs, 0x0400100C, 0x31080080);
|
||||||
mem.Write32<false>(regs, 0x04001000, 0x5500FFFC, regs.pc);
|
mem.Write32(regs, 0x04001000, 0x5500FFFC);
|
||||||
mem.Write32<false>(regs, 0x04001004, 0x3C0DBFC0, regs.pc);
|
mem.Write32(regs, 0x04001004, 0x3C0DBFC0);
|
||||||
mem.Write32<false>(regs, 0x04001008, 0x8DA80024, regs.pc);
|
mem.Write32(regs, 0x04001008, 0x8DA80024);
|
||||||
mem.Write32<false>(regs, 0x0400100C, 0x3C0BB000, regs.pc);
|
mem.Write32(regs, 0x0400100C, 0x3C0BB000);
|
||||||
break;
|
break;
|
||||||
case CIC_NUS_6106_7106:
|
case CIC_NUS_6106_7106:
|
||||||
regs.gpr[2] = (s64)0xFFFFFFFFA95930A4;
|
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 0x05: dmtc0(regs, instr); break;
|
||||||
case 0x10 ... 0x1F:
|
case 0x10 ... 0x1F:
|
||||||
switch(mask_cop2) {
|
switch(mask_cop2) {
|
||||||
case 0x01: tlbr(regs); break;
|
case 0x01: tlbr(); break;
|
||||||
case 0x02: tlbw(index & 0x3F, regs); break;
|
case 0x02: tlbw(index & 0x3F); break;
|
||||||
case 0x06: tlbw(GetRandom(), regs); break;
|
case 0x06: tlbw(GetRandom()); break;
|
||||||
case 0x08: tlbp(regs); break;
|
case 0x08: tlbp(regs); break;
|
||||||
case 0x18: eret(regs); break;
|
case 0x18: eret(regs); break;
|
||||||
default: Util::panic("Unimplemented COP0 function {} {} ({:08X}) ({:016lX})", mask_cop2 >> 3, mask_cop2 & 7, instr, regs.oldPC);
|
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 dmfc0(n64::Registers&, u32);
|
||||||
void eret(n64::Registers&);
|
void eret(n64::Registers&);
|
||||||
|
|
||||||
void tlbr(n64::Registers&);
|
void tlbr();
|
||||||
void tlbw(int, n64::Registers&);
|
void tlbw(int);
|
||||||
void tlbp(n64::Registers&);
|
void tlbp(n64::Registers&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user