minor fixes

This commit is contained in:
CocoSimone
2022-10-30 12:42:43 +01:00
parent 6222e9ebfd
commit 1265279069
4 changed files with 68 additions and 12 deletions

View File

@@ -115,6 +115,9 @@ void Cpu::Exec(Mem& mem, u32 instr) {
case 0x0F: lui(instr); break;
case 0x10: regs.cop0.decode(regs, mem, instr); break;
case 0x11: regs.cop1.decode(*this, instr); break;
case 0x12:
FireException(regs, ExceptionCode::CoprocessorUnusable, 2, regs.oldPC);
break;
case 0x14: bl(instr, regs.gpr[RS(instr)] == regs.gpr[RT(instr)]); break;
case 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break;

View File

@@ -9,7 +9,7 @@ Cop1::Cop1() {
}
void Cop1::Reset() {
fcr0 = 0;
fcr0 = 0xa00;
fcr31.raw = 0;
memset(fgr, 0, 32 * sizeof(FGR));
}
@@ -29,11 +29,11 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
case 0x00: mfc1(regs, instr); break;
case 0x01: dmfc1(regs, instr); break;
case 0x02: cfc1(regs, instr); break;
case 0x03: FireException(regs, ExceptionCode::FloatingPointError, 0, regs.oldPC); break;
case 0x03: FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC); break;
case 0x04: mtc1(regs, instr); break;
case 0x05: dmtc1(regs, instr); break;
case 0x06: ctc1(regs, instr); break;
case 0x07: FireException(regs, ExceptionCode::FloatingPointError, 0, regs.oldPC); break;
case 0x07: FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC); break;
case 0x08:
switch(mask_branch) {
case 0: cpu.b(instr, !regs.cop1.fcr31.compare); break;
@@ -61,6 +61,9 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
case 0x0D: truncws(regs, instr); break;
case 0x0E: ceilws(regs, instr); break;
case 0x0F: floorws(regs, instr); break;
case 0x20:
FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC);
break;
case 0x21: cvtds(regs, instr); break;
case 0x24: cvtws(regs, instr); break;
case 0x25: cvtls(regs, instr); break;
@@ -80,7 +83,7 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
case 0x3D: ccond<float>(regs, instr, NGE); break;
case 0x3E: ccond<float>(regs, instr, LE); break;
case 0x3F: ccond<float>(regs, instr, NGT); break;
default: util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016lX})", mask_fun >> 3, mask_fun & 7, instr, regs.oldPC);
default: util::panic("Unimplemented COP1 function S[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
}
break;
case 0x11: // d
@@ -102,6 +105,9 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
case 0x0E: ceilwd(regs, instr); break;
case 0x0F: floorwd(regs, instr); break;
case 0x20: cvtsd(regs, instr); break;
case 0x21:
FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC);
break;
case 0x24: cvtwd(regs, instr); break;
case 0x25: cvtld(regs, instr); break;
case 0x30: ccond<double>(regs, instr, F); break;
@@ -120,7 +126,7 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
case 0x3D: ccond<double>(regs, instr, NGE); break;
case 0x3E: ccond<double>(regs, instr, LE); break;
case 0x3F: ccond<double>(regs, instr, NGT); break;
default: util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016lX})", mask_fun >> 3, mask_fun & 7, instr, regs.oldPC);
default: util::panic("Unimplemented COP1 function D[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
}
break;
case 0x14: // w
@@ -131,7 +137,10 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
case 0x06: movw(regs, instr); break;
case 0x20: cvtsw(regs, instr); break;
case 0x21: cvtdw(regs, instr); break;
default: util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016lX})", mask_fun >> 3, mask_fun & 7, instr, regs.oldPC);
case 0x24:
FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC);
break;
default: util::panic("Unimplemented COP1 function W[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
}
break;
case 0x15: // l
@@ -142,7 +151,13 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
case 0x06: movl(regs, instr); break;
case 0x20: cvtsl(regs, instr); break;
case 0x21: cvtdl(regs, instr); break;
default: util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016lX})", mask_fun >> 3, mask_fun & 7, instr, regs.oldPC);
case 0x24:
FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC);
break;
case 0x25:
FireException(regs, ExceptionCode::ReservedInstruction, 1, regs.oldPC);
break;
default: util::panic("Unimplemented COP1 function L[{} {}] ({:08X}) ({:016X})", mask_fun >> 3, mask_fun & 7, instr, (u64)regs.oldPC);
}
break;
default: util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);

View File

@@ -28,7 +28,8 @@ union FCR31 {
} __attribute__((__packed__));
struct {
unsigned:7;
unsigned:2;
unsigned flag:5;
unsigned enable:5;
unsigned cause:6;
unsigned:14;

View File

@@ -1,7 +1,6 @@
#include <n64/core/cpu/registers/Cop1.hpp>
#include <n64/core/cpu/Registers.hpp>
#include <n64/core/Mem.hpp>
#include <util.hpp>
#include <cmath>
#include <cfenv>
@@ -21,6 +20,41 @@ inline int PushRoundingMode(const FCR31& fcr31) {
#define PUSHROUNDINGMODE int og = PushRoundingMode(fcr31)
#define POPROUNDINGMODE fesetround(og)
#ifdef _WIN32
#define isnanf isnan
#define checknanregsf(fs, ft) \
if(isnanf(fs) || isnanf(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, regs.oldPC); \
return; \
}
#define checknanregsd(fs, ft) \
if(isnan(fs) || isnan(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, regs.oldPC); \
return; \
}
#else
#define checknanregsf(fs, ft) \
if(isnanf(fs) || isnanf(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, regs.oldPC); \
return; \
}
#define checknanregsd(fs, ft) \
if(isnan(fs) || isnan(ft)) { \
regs.cop1.fcr31.flag_invalid_operation = true; \
regs.cop1.fcr31.cause_invalid_operation = true; \
FireException(regs, ExceptionCode::FloatingPointError, 1, regs.oldPC); \
return; \
}
#endif
void Cop1::absd(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
SetCop1Reg<double>(regs.cop0, FD(instr), fabs(fs));
@@ -44,6 +78,7 @@ void Cop1::absl(Registers& regs, u32 instr) {
void Cop1::adds(Registers& regs, u32 instr) {
float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
float ft = GetCop1Reg<float>(regs.cop0, FT(instr));
checknanregsf(fs, ft)
float result = fs + ft;
SetCop1Reg<float>(regs.cop0, FD(instr), result);
}
@@ -51,6 +86,7 @@ void Cop1::adds(Registers& regs, u32 instr) {
void Cop1::addd(Registers& regs, u32 instr) {
double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
double ft = GetCop1Reg<double>(regs.cop0, FT(instr));
checknanregsf(fs, ft)
double result = fs + ft;
SetCop1Reg<double>(regs.cop0, FD(instr), result);
}
@@ -83,8 +119,8 @@ void Cop1::cfc1(Registers& regs, u32 instr) const {
u8 fd = FD(instr);
s32 val = 0;
switch(fd) {
case 0: val = (s32)fcr0; break;
case 31: val = (s32)fcr31.raw; break;
case 0: val = fcr0; break;
case 31: val = fcr31.raw; break;
default: util::panic("Undefined CFC1 with rd != 0 or 31\n");
}
regs.gpr[RT(instr)] = val;
@@ -228,7 +264,8 @@ inline bool CalculateCondition(Registers& regs, T fs, T ft, CompConds cond) {
if(std::isnan(fs) || std::isnan(ft)) {
regs.cop1.fcr31.flag_invalid_operation = true;
regs.cop1.fcr31.cause_invalid_operation = true;
FireException(regs, ExceptionCode::FloatingPointError, 0, regs.oldPC);
FireException(regs, ExceptionCode::FloatingPointError, 1, regs.oldPC);
return false;
}
return CalculateCondition(regs, fs, ft, static_cast<CompConds>(cond - 8));