SSV and SLV switched, fix shift in SBV, implement "Dump RDRAM" and "Dump IMEM" buttons in GUI

This commit is contained in:
CocoSimone
2022-10-06 02:17:36 +02:00
parent 89daa969eb
commit 73d65c2246
6 changed files with 101 additions and 49 deletions

View File

@@ -13,14 +13,9 @@ void App::Run() {
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
ImGui_ImplSDL2_ProcessEvent(&event); ImGui_ImplSDL2_ProcessEvent(&event);
switch(event.type) { switch(event.type) {
case SDL_QUIT: { case SDL_QUIT:
core.done = true; core.done = true;
FILE *fp = fopen("rdram.dump", "wb"); break;
u8 *temp = core.mem.GetRDRAM();
util::SwapBuffer32(RDRAM_SIZE, temp);
fwrite(temp, 1, RDRAM_SIZE, fp);
fclose(fp);
} break;
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
core.done = window.gotClosed(event); core.done = window.gotClosed(event);
break; break;

View File

@@ -182,6 +182,20 @@ void Window::Render(n64::Core& core) {
NFD_FreePath(outpath); NFD_FreePath(outpath);
} }
} }
if (ImGui::MenuItem("Dump RDRAM")) {
FILE *fp = fopen("rdram.dump", "wb");
u8 *temp = core.mem.GetRDRAM();
util::SwapBuffer32(RDRAM_SIZE, temp);
fwrite(temp, 1, RDRAM_SIZE, fp);
fclose(fp);
}
if (ImGui::MenuItem("Dump IMEM")) {
FILE *fp = fopen("imem.dump", "wb");
u8 *temp = core.mem.mmio.rsp.imem;
util::SwapBuffer32(IMEM_SIZE, temp);
fwrite(temp, 1, IMEM_SIZE, fp);
fclose(fp);
}
if (ImGui::MenuItem("Exit")) { if (ImGui::MenuItem("Exit")) {
core.done = true; core.done = true;
} }

View File

@@ -80,7 +80,7 @@ u8 Mem::Read8(n64::Registers &regs, u64 vaddr, s64 pc) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
return mmio.rdp.dram[BYTE_ADDRESS(paddr) & RDRAM_DSIZE]; return mmio.rdp.dram[BYTE_ADDRESS(paddr) & RDRAM_DSIZE];
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if(paddr & 0x1000) if((paddr >> 12) & 1)
return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE]; return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE];
else else
return mmio.rsp.dmem[BYTE_ADDRESS(paddr) & DMEM_DSIZE]; return mmio.rsp.dmem[BYTE_ADDRESS(paddr) & DMEM_DSIZE];
@@ -113,7 +113,7 @@ u16 Mem::Read16(n64::Registers &regs, u64 vaddr, s64 pc) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr) & RDRAM_DSIZE); return util::ReadAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr) & RDRAM_DSIZE);
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if(paddr & 0x1000) if((paddr >> 12) & 1)
return util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE); return util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE);
else else
return util::ReadAccess<u16>(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE); return util::ReadAccess<u16>(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE);
@@ -146,7 +146,7 @@ u32 Mem::Read32(n64::Registers &regs, u64 vaddr, s64 pc) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u32>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE); return util::ReadAccess<u32>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE);
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if(paddr & 0x1000) if((paddr >> 12) & 1)
return util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE); return util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE);
else else
return util::ReadAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE); return util::ReadAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE);
@@ -178,7 +178,7 @@ u64 Mem::Read64(n64::Registers &regs, u64 vaddr, s64 pc) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u64>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE); return util::ReadAccess<u64>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE);
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if(paddr & 0x1000) if((paddr >> 12) & 1)
return util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE); return util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE);
else else
return util::ReadAccess<u64>(mmio.rsp.dmem, paddr & DMEM_DSIZE); return util::ReadAccess<u64>(mmio.rsp.dmem, paddr & DMEM_DSIZE);
@@ -222,7 +222,7 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
val = val << (8 * (3 - (paddr & 3))); val = val << (8 * (3 - (paddr & 3)));
paddr = (paddr & DMEM_DSIZE) & ~3; paddr = (paddr & DMEM_DSIZE) & ~3;
if(paddr & 0x1000) if((paddr >> 12) & 1)
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
else else
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
@@ -258,7 +258,7 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
val = val << (16 * !(paddr & 2)); val = val << (16 * !(paddr & 2));
paddr &= ~3; paddr &= ~3;
if(paddr & 0x1000) if((paddr >> 12) & 1)
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
else else
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
@@ -292,7 +292,7 @@ void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
util::WriteAccess<u32>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE, val); util::WriteAccess<u32>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE, val);
break; break;
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if(paddr & 0x1000) if((paddr >> 12) & 1)
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
else else
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
@@ -336,7 +336,7 @@ void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
break; break;
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
val >>= 32; val >>= 32;
if(paddr & 0x1000) if((paddr >> 12) & 1)
util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
else else
util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);

View File

@@ -218,6 +218,7 @@ struct RSP {
} }
inline u64 ReadDword(u32 addr, bool i) { inline u64 ReadDword(u32 addr, bool i) {
addr &= 0xfff;
if (i) { if (i) {
return GET_RSP_DWORD(addr, imem); return GET_RSP_DWORD(addr, imem);
} else { } else {
@@ -226,6 +227,7 @@ struct RSP {
} }
inline void WriteDword(u32 addr, u64 val, bool i) { inline void WriteDword(u32 addr, u64 val, bool i) {
addr &= 0xfff;
if (i) { if (i) {
SET_RSP_DWORD(addr, imem, val); SET_RSP_DWORD(addr, imem, val);
} else { } else {
@@ -234,6 +236,7 @@ struct RSP {
} }
inline u32 ReadWord(u32 addr, bool i) { inline u32 ReadWord(u32 addr, bool i) {
addr &= 0xfff;
if (i) { if (i) {
return GET_RSP_WORD(addr, imem); return GET_RSP_WORD(addr, imem);
} else { } else {
@@ -242,6 +245,7 @@ struct RSP {
} }
inline void WriteWord(u32 addr, u32 val, bool i) { inline void WriteWord(u32 addr, u32 val, bool i) {
addr &= 0xfff;
if (i) { if (i) {
SET_RSP_WORD(addr, imem, val); SET_RSP_WORD(addr, imem, val);
} else { } else {
@@ -250,6 +254,7 @@ struct RSP {
} }
inline u16 ReadHalf(u32 addr, bool i) { inline u16 ReadHalf(u32 addr, bool i) {
addr &= 0xfff;
if (i) { if (i) {
return GET_RSP_HALF(addr, imem); return GET_RSP_HALF(addr, imem);
} else { } else {
@@ -258,6 +263,7 @@ struct RSP {
} }
inline void WriteHalf(u32 addr, u16 val, bool i) { inline void WriteHalf(u32 addr, u16 val, bool i) {
addr &= 0xfff;
if (i) { if (i) {
SET_RSP_HALF(addr, imem, val); SET_RSP_HALF(addr, imem, val);
} else { } else {
@@ -266,6 +272,7 @@ struct RSP {
} }
inline u8 ReadByte(u32 addr, bool i) { inline u8 ReadByte(u32 addr, bool i) {
addr &= 0xfff;
if (i) { if (i) {
return RSP_BYTE(addr, imem); return RSP_BYTE(addr, imem);
} else { } else {
@@ -274,6 +281,7 @@ struct RSP {
} }
inline void WriteByte(u32 addr, u8 val, bool i) { inline void WriteByte(u32 addr, u8 val, bool i) {
addr &= 0xfff;
if (i) { if (i) {
RSP_BYTE(addr, imem) = val; RSP_BYTE(addr, imem) = val;
} else { } else {
@@ -282,34 +290,42 @@ struct RSP {
} }
inline u64 ReadDword(u32 addr) { inline u64 ReadDword(u32 addr) {
addr &= 0xfff;
return GET_RSP_DWORD(addr, dmem); return GET_RSP_DWORD(addr, dmem);
} }
inline void WriteDword(u32 addr, u64 val) { inline void WriteDword(u32 addr, u64 val) {
addr &= 0xfff;
SET_RSP_DWORD(addr, dmem, val); SET_RSP_DWORD(addr, dmem, val);
} }
inline u32 ReadWord(u32 addr) { inline u32 ReadWord(u32 addr) {
addr &= 0xfff;
return GET_RSP_WORD(addr, dmem); return GET_RSP_WORD(addr, dmem);
} }
inline void WriteWord(u32 addr, u32 val) { inline void WriteWord(u32 addr, u32 val) {
addr &= 0xfff;
SET_RSP_WORD(addr, dmem, val); SET_RSP_WORD(addr, dmem, val);
} }
inline u16 ReadHalf(u32 addr) { inline u16 ReadHalf(u32 addr) {
addr &= 0xfff;
return GET_RSP_HALF(addr, dmem); return GET_RSP_HALF(addr, dmem);
} }
inline void WriteHalf(u32 addr, u16 val) { inline void WriteHalf(u32 addr, u16 val) {
addr &= 0xfff;
SET_RSP_HALF(addr, dmem, val); SET_RSP_HALF(addr, dmem, val);
} }
inline u8 ReadByte(u32 addr) { inline u8 ReadByte(u32 addr) {
addr &= 0xfff;
return RSP_BYTE(addr, dmem); return RSP_BYTE(addr, dmem);
} }
inline void WriteByte(u32 addr, u8 val) { inline void WriteByte(u32 addr, u8 val) {
addr &= 0xfff;
RSP_BYTE(addr, dmem) = val; RSP_BYTE(addr, dmem) = val;
} }
@@ -411,7 +427,8 @@ struct RSP {
void vsub(u32 instr); void vsub(u32 instr);
void vsubc(u32 instr); void vsubc(u32 instr);
void vxor(u32 instr); void vxor(u32 instr);
void vxnor(u32 instr); void vnxor(u32 instr);
void vor(u32 instr);
void vnor(u32 instr); void vnor(u32 instr);
void vzero(u32 instr); void vzero(u32 instr);
void mfc0(RDP& rdp, u32 instr); void mfc0(RDP& rdp, u32 instr);

View File

@@ -77,8 +77,8 @@ inline void swc2(RSP& rsp, u32 instr) {
//util::print("swc2 {:02X}\n", mask); //util::print("swc2 {:02X}\n", mask);
switch(mask) { switch(mask) {
case 0x00: rsp.sbv(instr); break; case 0x00: rsp.sbv(instr); break;
case 0x01: rsp.slv(instr); break; case 0x01: rsp.ssv(instr); break;
case 0x02: rsp.ssv(instr); break; case 0x02: rsp.slv(instr); break;
case 0x03: rsp.sdv(instr); break; case 0x03: rsp.sdv(instr); break;
case 0x04: rsp.sqv(instr); break; case 0x04: rsp.sqv(instr); break;
case 0x06: rsp.spv(instr); break; case 0x06: rsp.spv(instr); break;
@@ -100,8 +100,10 @@ inline void cop2(RSP& rsp, u32 instr) {
case 0x02: rsp.cfc2(instr); break; case 0x02: rsp.cfc2(instr); break;
case 0x04: rsp.mtc2(instr); break; case 0x04: rsp.mtc2(instr); break;
case 0x06: rsp.ctc2(instr); break; case 0x06: rsp.ctc2(instr); break;
case 0x10: case 0x1C: case 0x1E: case 0x10: case 0x14:
case 0x1F: case 0x14: break; //rsp.vzero(instr); break; case 0x1C: case 0x1E: case 0x1F:
util::print("Invalid COP2 SUB {:05b} at PC: {:016X}\n", mask_sub, rsp.oldPC);
break;
default: util::panic("Unhandled RSP COP2 sub ({:05b})\n", mask_sub); default: util::panic("Unhandled RSP COP2 sub ({:05b})\n", mask_sub);
} }
break; break;
@@ -130,9 +132,10 @@ inline void cop2(RSP& rsp, u32 instr) {
case 0x27: rsp.vmrg(instr); break; case 0x27: rsp.vmrg(instr); break;
case 0x28: rsp.vand(instr); break; case 0x28: rsp.vand(instr); break;
case 0x29: rsp.vnand(instr); break; case 0x29: rsp.vnand(instr); break;
case 0x2A: rsp.vnor(instr); break; case 0x2A: rsp.vor(instr); break;
case 0x2B: rsp.vnor(instr); break;
case 0x2C: rsp.vxor(instr); break; case 0x2C: rsp.vxor(instr); break;
case 0x2D: rsp.vxnor(instr); break; case 0x2D: rsp.vnxor(instr); break;
case 0x31: rsp.vrcpl(instr); break; case 0x31: rsp.vrcpl(instr); break;
case 0x35: rsp.vrsql(instr); break; case 0x35: rsp.vrsql(instr); break;
case 0x32: case 0x36: case 0x32: case 0x36:
@@ -141,6 +144,8 @@ inline void cop2(RSP& rsp, u32 instr) {
case 0x30: rsp.vrcp(instr); break; case 0x30: rsp.vrcp(instr); break;
case 0x33: rsp.vmov(instr); break; case 0x33: rsp.vmov(instr); break;
case 0x34: rsp.vrsq(instr); break; case 0x34: rsp.vrsq(instr); break;
case 0x37: break;
case 0x3F: break;
default: util::panic("Unhandled RSP COP2 ({:06b})\n", mask); default: util::panic("Unhandled RSP COP2 ({:06b})\n", mask);
} }
} }

View File

@@ -97,11 +97,23 @@ inline VPR GetVTE(VPR vt, u8 e) {
VPR vte{}; VPR vte{};
switch(e & 0xf) { switch(e & 0xf) {
case 0 ... 1: return vt; case 0 ... 1: return vt;
case 2 ... 3: case 2:
vte = Broadcast(vt, e - 2, e - 2, e, e, e + 2, e + 2, e + 4, e + 4); vte = Broadcast(vt, 0, 0, 2, 2, 4, 4, 6, 6);
break; break;
case 4 ... 7: case 3:
vte = Broadcast(vt, e - 4, e - 4, e - 4, e - 4, e, e, e, e); vte = Broadcast(vt, 1, 1, 3, 3, 5, 5, 7, 7);
break;
case 4:
vte = Broadcast(vt, 0, 0, 0, 0, 4, 4, 4, 4);
break;
case 5:
vte = Broadcast(vt, 1, 1, 1, 1, 5, 5, 5, 5);
break;
case 6:
vte = Broadcast(vt, 2, 2, 2, 2, 6, 6, 6, 6);
break;
case 7:
vte = Broadcast(vt, 3, 3, 3, 3, 7, 7, 7, 7);
break; break;
case 8 ... 15: { case 8 ... 15: {
int index = ELEMENT_INDEX(e - 8); int index = ELEMENT_INDEX(e - 8);
@@ -289,7 +301,7 @@ void RSP::ldv(u32 instr) {
} }
void RSP::lsv(u32 instr) { void RSP::lsv(u32 instr) {
int e = E1(instr); u8 e = E1(instr);
u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 1); u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 1);
u16 val = ReadHalf(addr); u16 val = ReadHalf(addr);
vpr[VT(instr)].byte[BYTE_INDEX(e)] = val >> 8; vpr[VT(instr)].byte[BYTE_INDEX(e)] = val >> 8;
@@ -404,7 +416,7 @@ void RSP::spv(u32 instr) {
void RSP::sbv(u32 instr) { void RSP::sbv(u32 instr) {
int e = E1(instr); int e = E1(instr);
u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 3); u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 0);
WriteByte(addr, vpr[VT(instr)].byte[BYTE_INDEX(e & 0xF)]); WriteByte(addr, vpr[VT(instr)].byte[BYTE_INDEX(e & 0xF)]);
} }
@@ -583,7 +595,7 @@ void RSP::vaddc(u32 instr) {
VPR vte = GetVTE(vpr[VT(instr)], E2(instr)); VPR vte = GetVTE(vpr[VT(instr)], E2(instr));
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
s32 result = vs.selement[i] + vte.selement[i]; u32 result = vs.element[i] + vte.element[i];
acc.l.element[i] = result; acc.l.element[i] = result;
vd.element[i] = result; vd.element[i] = result;
vco.l.element[i] = (result >> 16) & 1 ? 0xffff : 0; vco.l.element[i] = (result >> 16) & 1 ? 0xffff : 0;
@@ -663,17 +675,15 @@ void RSP::vcl(u32 instr) {
VPR vte = GetVTE(vpr[VT(instr)], e); VPR vte = GetVTE(vpr[VT(instr)], e);
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
s16 vsElem = vs.selement[i]; u16 vsElem = vs.element[i];
s16 vteElem = vte.selement[i]; u16 vteElem = vte.element[i];
if(vco.l.element[i]) {
if(vco.h.element[i]) {
acc.l.element[i] = vcc.l.element[i] ? -vteElem : vsElem; acc.l.element[i] = vcc.l.element[i] ? -vteElem : vsElem;
} else { if(vco.l.element[i]) {
if(!vco.h.element[i]) {
u16 clampSum = vsElem + vteElem; u16 clampSum = vsElem + vteElem;
bool overflow = (vsElem + vteElem) != clampSum; bool overflow = (vsElem + vteElem) != clampSum;
acc.l.element[i] = vcc.l.element[i] ? -vteElem : vsElem;
if(vce.element[i]) { if(vce.element[i]) {
vcc.l.element[i] = !clampSum || !overflow ? 0xffff : 0; vcc.l.element[i] = !clampSum || !overflow ? 0xffff : 0;
} else { } else {
@@ -681,9 +691,8 @@ void RSP::vcl(u32 instr) {
} }
} }
} else { } else {
acc.l.element[i] = vcc.l.element[i] ? -vteElem : vsElem;
if(!vco.h.element[i]) { if(!vco.h.element[i]) {
vcc.h.element[i] = s32(vsElem) - s32(vteElem) >= 0 ? 0xffff : 0; vcc.h.element[i] = (s32(vsElem) - s32(vteElem) >= 0) ? 0xffff : 0;
} }
} }
@@ -699,7 +708,7 @@ void RSP::vmov(u32 instr) {
VPR& vd = vpr[VD(instr)]; VPR& vd = vpr[VD(instr)];
VPR vte = GetVTE(vpr[VT(instr)], e); VPR vte = GetVTE(vpr[VT(instr)], e);
u32 se; /*u8 se;
switch (e) { switch (e) {
case 0 ... 1: case 0 ... 1:
@@ -716,11 +725,11 @@ void RSP::vmov(u32 instr) {
break; break;
default: default:
util::panic("VMOV: This should be unreachable!\n"); util::panic("VMOV: This should be unreachable!\n");
} }*/
u8 de = VS(instr) & 7; u8 de = VS(instr) & 7;
vd.element[ELEMENT_INDEX(de)] = vte.element[ELEMENT_INDEX(se)]; vd.element[ELEMENT_INDEX(de)] = vte.element[ELEMENT_INDEX(de)];
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
acc.l.element[i] = vte.element[i]; acc.l.element[i] = vte.element[i];
} }
@@ -950,7 +959,7 @@ void RSP::vge(u32 instr) {
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
bool eql = vs.element[i] == vte.element[i]; bool eql = vs.element[i] == vte.element[i];
bool neg = !(vco.h.element[i] & vco.l.element[i]) & eql; bool neg = !(vco.h.element[i] && vco.l.element[i]) && eql;
vcc.l.element[i] = (neg || (vs.element[i] > vte.element[i])) ? 0xffff : 0; vcc.l.element[i] = (neg || (vs.element[i] > vte.element[i])) ? 0xffff : 0;
acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i];
vd.element[i] = acc.l.element[i]; vd.element[i] = acc.l.element[i];
@@ -966,8 +975,8 @@ void RSP::vlt(u32 instr) {
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
bool eql = vs.element[i] == vte.element[i]; bool eql = vs.element[i] == vte.element[i];
bool neg = vco.h.element[i] & vco.l.element[i] & eql; bool neg = vco.h.element[i] && vco.l.element[i] && eql;
vcc.l.element[i] = (neg || (vs.element[i] < vte.element[i])) ? 0xffff : 0; vcc.l.element[i] = (neg || (vs.selement[i] < vte.selement[i])) ? 0xffff : 0;
acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i];
vd.element[i] = acc.l.element[i]; vd.element[i] = acc.l.element[i];
vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0;
@@ -1105,11 +1114,11 @@ void RSP::vrsql(u32 instr) {
} }
void RSP::vrcph(u32 instr) { void RSP::vrcph(u32 instr) {
int e = E2(instr); int e = E2(instr) & 7;
int de = DE(instr); int de = DE(instr) & 7;
VPR& vd = vpr[VD(instr)]; VPR& vd = vpr[VD(instr)];
VPR& vt = vpr[VT(instr)]; VPR& vt = vpr[VT(instr)];
VPR vte = GetVTE(vpr[VT(instr)], e); VPR vte = GetVTE(vpr[VT(instr)], E2(instr));
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
acc.l.element[i] = vte.element[i]; acc.l.element[i] = vte.element[i];
@@ -1169,9 +1178,9 @@ void RSP::vsub(u32 instr) {
VPR vte = GetVTE(vpr[VT(instr)], e); VPR vte = GetVTE(vpr[VT(instr)], e);
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
u32 result = vs.element[i] - vte.element[i] - vco.l.element[i]; s32 result = vs.selement[i] - vte.selement[i] - (vco.l.element[i] != 0);
acc.l.element[i] = result; acc.l.element[i] = result;
vd.element[i] = clamp_signed(s32(result) & 0x1FFFF); vd.element[i] = clamp_signed(result);
vco.l.element[i] = 0; vco.l.element[i] = 0;
vco.h.element[i] = 0; vco.h.element[i] = 0;
@@ -1202,7 +1211,7 @@ void RSP::vxor(u32 instr) {
} }
} }
void RSP::vxnor(u32 instr) { void RSP::vnxor(u32 instr) {
int e = E2(instr); int e = E2(instr);
VPR& vs = vpr[VS(instr)]; VPR& vs = vpr[VS(instr)];
VPR& vd = vpr[VD(instr)]; VPR& vd = vpr[VD(instr)];
@@ -1250,6 +1259,18 @@ void RSP::vnor(u32 instr) {
} }
} }
void RSP::vor(u32 instr) {
int e = E2(instr);
VPR& vs = vpr[VS(instr)];
VPR& vd = vpr[VD(instr)];
VPR vte = GetVTE(vpr[VT(instr)], e);
for(int i = 0; i < 8; i++) {
acc.l.element[i] = vte.element[i] | vs.element[i];
vd.element[i] = acc.l.element[i];
}
}
void RSP::vzero(u32 instr) { void RSP::vzero(u32 instr) {
VPR& vs = vpr[VS(instr)]; VPR& vs = vpr[VS(instr)];
VPR& vd = vpr[VD(instr)]; VPR& vd = vpr[VD(instr)];