minor fixes
This commit is contained in:
@@ -115,6 +115,9 @@ void Cpu::Exec(Mem& mem, u32 instr) {
|
|||||||
case 0x0F: lui(instr); break;
|
case 0x0F: lui(instr); break;
|
||||||
case 0x10: regs.cop0.decode(regs, mem, instr); break;
|
case 0x10: regs.cop0.decode(regs, mem, instr); break;
|
||||||
case 0x11: regs.cop1.decode(*this, 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 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 0x15: bl(instr, regs.gpr[RS(instr)] != regs.gpr[RT(instr)]); break;
|
||||||
case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break;
|
case 0x16: bl(instr, regs.gpr[RS(instr)] <= 0); break;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Cop1::Cop1() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cop1::Reset() {
|
void Cop1::Reset() {
|
||||||
fcr0 = 0;
|
fcr0 = 0xa00;
|
||||||
fcr31.raw = 0;
|
fcr31.raw = 0;
|
||||||
memset(fgr, 0, 32 * sizeof(FGR));
|
memset(fgr, 0, 32 * sizeof(FGR));
|
||||||
}
|
}
|
||||||
@@ -29,11 +29,11 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
|
|||||||
case 0x00: mfc1(regs, instr); break;
|
case 0x00: mfc1(regs, instr); break;
|
||||||
case 0x01: dmfc1(regs, instr); break;
|
case 0x01: dmfc1(regs, instr); break;
|
||||||
case 0x02: cfc1(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 0x04: mtc1(regs, instr); break;
|
||||||
case 0x05: dmtc1(regs, instr); break;
|
case 0x05: dmtc1(regs, instr); break;
|
||||||
case 0x06: ctc1(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:
|
case 0x08:
|
||||||
switch(mask_branch) {
|
switch(mask_branch) {
|
||||||
case 0: cpu.b(instr, !regs.cop1.fcr31.compare); break;
|
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 0x0D: truncws(regs, instr); break;
|
||||||
case 0x0E: ceilws(regs, instr); break;
|
case 0x0E: ceilws(regs, instr); break;
|
||||||
case 0x0F: floorws(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 0x21: cvtds(regs, instr); break;
|
||||||
case 0x24: cvtws(regs, instr); break;
|
case 0x24: cvtws(regs, instr); break;
|
||||||
case 0x25: cvtls(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 0x3D: ccond<float>(regs, instr, NGE); break;
|
||||||
case 0x3E: ccond<float>(regs, instr, LE); break;
|
case 0x3E: ccond<float>(regs, instr, LE); break;
|
||||||
case 0x3F: ccond<float>(regs, instr, NGT); 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;
|
break;
|
||||||
case 0x11: // d
|
case 0x11: // d
|
||||||
@@ -102,6 +105,9 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
|
|||||||
case 0x0E: ceilwd(regs, instr); break;
|
case 0x0E: ceilwd(regs, instr); break;
|
||||||
case 0x0F: floorwd(regs, instr); break;
|
case 0x0F: floorwd(regs, instr); break;
|
||||||
case 0x20: cvtsd(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 0x24: cvtwd(regs, instr); break;
|
||||||
case 0x25: cvtld(regs, instr); break;
|
case 0x25: cvtld(regs, instr); break;
|
||||||
case 0x30: ccond<double>(regs, instr, F); 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 0x3D: ccond<double>(regs, instr, NGE); break;
|
||||||
case 0x3E: ccond<double>(regs, instr, LE); break;
|
case 0x3E: ccond<double>(regs, instr, LE); break;
|
||||||
case 0x3F: ccond<double>(regs, instr, NGT); 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;
|
break;
|
||||||
case 0x14: // w
|
case 0x14: // w
|
||||||
@@ -131,7 +137,10 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
|
|||||||
case 0x06: movw(regs, instr); break;
|
case 0x06: movw(regs, instr); break;
|
||||||
case 0x20: cvtsw(regs, instr); break;
|
case 0x20: cvtsw(regs, instr); break;
|
||||||
case 0x21: cvtdw(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;
|
break;
|
||||||
case 0x15: // l
|
case 0x15: // l
|
||||||
@@ -142,7 +151,13 @@ void Cop1::decode(Cpu& cpu, u32 instr) {
|
|||||||
case 0x06: movl(regs, instr); break;
|
case 0x06: movl(regs, instr); break;
|
||||||
case 0x20: cvtsl(regs, instr); break;
|
case 0x20: cvtsl(regs, instr); break;
|
||||||
case 0x21: cvtdl(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;
|
break;
|
||||||
default: util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
default: util::panic("Unimplemented COP1 instruction {} {}", mask_sub >> 3, mask_sub & 7);
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ union FCR31 {
|
|||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
unsigned:7;
|
unsigned:2;
|
||||||
|
unsigned flag:5;
|
||||||
unsigned enable:5;
|
unsigned enable:5;
|
||||||
unsigned cause:6;
|
unsigned cause:6;
|
||||||
unsigned:14;
|
unsigned:14;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <n64/core/cpu/registers/Cop1.hpp>
|
#include <n64/core/cpu/registers/Cop1.hpp>
|
||||||
#include <n64/core/cpu/Registers.hpp>
|
#include <n64/core/cpu/Registers.hpp>
|
||||||
#include <n64/core/Mem.hpp>
|
#include <n64/core/Mem.hpp>
|
||||||
#include <util.hpp>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cfenv>
|
#include <cfenv>
|
||||||
|
|
||||||
@@ -21,6 +20,41 @@ inline int PushRoundingMode(const FCR31& fcr31) {
|
|||||||
#define PUSHROUNDINGMODE int og = PushRoundingMode(fcr31)
|
#define PUSHROUNDINGMODE int og = PushRoundingMode(fcr31)
|
||||||
#define POPROUNDINGMODE fesetround(og)
|
#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) {
|
void Cop1::absd(Registers& regs, u32 instr) {
|
||||||
double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
|
double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
|
||||||
SetCop1Reg<double>(regs.cop0, FD(instr), fabs(fs));
|
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) {
|
void Cop1::adds(Registers& regs, u32 instr) {
|
||||||
float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
|
float fs = GetCop1Reg<float>(regs.cop0, FS(instr));
|
||||||
float ft = GetCop1Reg<float>(regs.cop0, FT(instr));
|
float ft = GetCop1Reg<float>(regs.cop0, FT(instr));
|
||||||
|
checknanregsf(fs, ft)
|
||||||
float result = fs + ft;
|
float result = fs + ft;
|
||||||
SetCop1Reg<float>(regs.cop0, FD(instr), result);
|
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) {
|
void Cop1::addd(Registers& regs, u32 instr) {
|
||||||
double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
|
double fs = GetCop1Reg<double>(regs.cop0, FS(instr));
|
||||||
double ft = GetCop1Reg<double>(regs.cop0, FT(instr));
|
double ft = GetCop1Reg<double>(regs.cop0, FT(instr));
|
||||||
|
checknanregsf(fs, ft)
|
||||||
double result = fs + ft;
|
double result = fs + ft;
|
||||||
SetCop1Reg<double>(regs.cop0, FD(instr), result);
|
SetCop1Reg<double>(regs.cop0, FD(instr), result);
|
||||||
}
|
}
|
||||||
@@ -83,8 +119,8 @@ void Cop1::cfc1(Registers& regs, u32 instr) const {
|
|||||||
u8 fd = FD(instr);
|
u8 fd = FD(instr);
|
||||||
s32 val = 0;
|
s32 val = 0;
|
||||||
switch(fd) {
|
switch(fd) {
|
||||||
case 0: val = (s32)fcr0; break;
|
case 0: val = fcr0; break;
|
||||||
case 31: val = (s32)fcr31.raw; break;
|
case 31: val = fcr31.raw; break;
|
||||||
default: util::panic("Undefined CFC1 with rd != 0 or 31\n");
|
default: util::panic("Undefined CFC1 with rd != 0 or 31\n");
|
||||||
}
|
}
|
||||||
regs.gpr[RT(instr)] = val;
|
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)) {
|
if(std::isnan(fs) || std::isnan(ft)) {
|
||||||
regs.cop1.fcr31.flag_invalid_operation = true;
|
regs.cop1.fcr31.flag_invalid_operation = true;
|
||||||
regs.cop1.fcr31.cause_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));
|
return CalculateCondition(regs, fs, ft, static_cast<CompConds>(cond - 8));
|
||||||
|
|||||||
Reference in New Issue
Block a user