minor fixes
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -28,7 +28,8 @@ union FCR31 {
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct {
|
||||
unsigned:7;
|
||||
unsigned:2;
|
||||
unsigned flag:5;
|
||||
unsigned enable:5;
|
||||
unsigned cause:6;
|
||||
unsigned:14;
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user