#pragma once #include #include namespace n64 { struct Cop1; union FCR31 { FCR31() = default; struct { unsigned rounding_mode : 2; struct { unsigned inexact_operation : 1; unsigned underflow : 1; unsigned overflow : 1; unsigned division_by_zero : 1; unsigned invalid_operation : 1; } flag; struct { unsigned inexact_operation : 1; unsigned underflow : 1; unsigned overflow : 1; unsigned division_by_zero : 1; unsigned invalid_operation : 1; } enable; struct { unsigned inexact_operation : 1; unsigned underflow : 1; unsigned overflow : 1; unsigned division_by_zero : 1; unsigned invalid_operation : 1; unsigned unimplemented_operation : 1; } cause; unsigned : 5; unsigned compare : 1; unsigned fs : 1; unsigned : 7; } __attribute__((__packed__)); [[nodiscard]] u32 read() const { u32 ret = 0; ret |= (u32(fs) << 24); ret |= (u32(compare) << 23); ret |= (u32(cause.unimplemented_operation) << 17); ret |= (u32(cause.invalid_operation) << 16); ret |= (u32(cause.division_by_zero) << 15); ret |= (u32(cause.overflow) << 14); ret |= (u32(cause.underflow) << 13); ret |= (u32(cause.inexact_operation) << 12); ret |= (u32(enable.invalid_operation) << 11); ret |= (u32(enable.division_by_zero) << 10); ret |= (u32(enable.overflow) << 9); ret |= (u32(enable.underflow) << 8); ret |= (u32(enable.inexact_operation) << 7); ret |= (u32(flag.invalid_operation) << 6); ret |= (u32(flag.division_by_zero) << 5); ret |= (u32(flag.overflow) << 4); ret |= (u32(flag.underflow) << 3); ret |= (u32(flag.inexact_operation) << 2); ret |= (u32(rounding_mode) & 3); return ret; } void write(u32 val) { fs = val >> 24; compare = val >> 23; cause.unimplemented_operation = val >> 17; cause.invalid_operation = val >> 16; cause.division_by_zero = val >> 15; cause.overflow = val >> 14; cause.underflow = val >> 13; cause.inexact_operation = val >> 12; enable.invalid_operation = val >> 11; enable.division_by_zero = val >> 10; enable.overflow = val >> 9; enable.underflow = val >> 8; enable.inexact_operation = val >> 7; flag.invalid_operation = val >> 6; flag.division_by_zero = val >> 5; flag.overflow = val >> 4; flag.underflow = val >> 3; flag.inexact_operation = val >> 2; rounding_mode = val & 3; } }; union FloatingPointReg { struct { s32 int32; s32 int32h; }; struct { u32 uint32; u32 uint32h; }; struct { s64 int64; }; struct { u64 uint64; }; struct { float float32; float float32h; }; struct { double float64; }; }; struct Cop1 { explicit Cop1(); u32 fcr0{}; FCR31 fcr31{}; FloatingPointReg fgr[32]{}; bool fgrIsConstant[32]{}; void Reset(); void decode(u32); friend struct Interpreter; friend struct JIT; template bool CheckFPUUsable(); template bool CheckResult(T &); template bool CheckArg(T); template bool CheckArgs(T, T); template bool isqnan(T); template bool XORDERED(T fs, T ft); template bool CheckCVTArg(float f); template bool CheckCVTArg(double f); template bool TestExceptions(); void SetCauseUnimplemented(); bool SetCauseUnderflow(); bool SetCauseInexact(); bool SetCauseDivisionByZero(); bool SetCauseOverflow(); bool SetCauseInvalid(); private: template auto FGR_T(const Cop0Status &, u32) -> T &; template auto FGR_S(const Cop0Status &, u32) -> T &; template auto FGR_D(const Cop0Status &, u32) -> T &; void absd(u32 instr); void abss(u32 instr); void adds(u32 instr); void addd(u32 instr); void subs(u32 instr); void subd(u32 instr); void ceills(u32 instr); void ceilws(u32 instr); void ceilld(u32 instr); void ceilwd(u32 instr); void cfc1(u32 instr); void ctc1(u32 instr); void unimplemented(); void roundls(u32 instr); void roundld(u32 instr); void roundws(u32 instr); void roundwd(u32 instr); void floorls(u32 instr); void floorld(u32 instr); void floorws(u32 instr); void floorwd(u32 instr); void cvtls(u32 instr); void cvtws(u32 instr); void cvtds(u32 instr); void cvtsw(u32 instr); void cvtdw(u32 instr); void cvtsd(u32 instr); void cvtwd(u32 instr); void cvtld(u32 instr); void cvtdl(u32 instr); void cvtsl(u32 instr); template void cf(u32 instr); template void cun(u32 instr); template void ceq(u32 instr); template void cueq(u32 instr); template void colt(u32 instr); template void cult(u32 instr); template void cole(u32 instr); template void cule(u32 instr); template void csf(u32 instr); template void cngle(u32 instr); template void cseq(u32 instr); template void cngl(u32 instr); template void clt(u32 instr); template void cnge(u32 instr); template void cle(u32 instr); template void cngt(u32 instr); void divs(u32 instr); void divd(u32 instr); void muls(u32 instr); void muld(u32 instr); void movs(u32 instr); void movd(u32 instr); void negs(u32 instr); void negd(u32 instr); void sqrts(u32 instr); void sqrtd(u32 instr); void lwc1(u32); void swc1(u32); void ldc1(u32); void sdc1(u32); void mfc1(u32 instr); void dmfc1(u32 instr); void mtc1(u32 instr); void dmtc1(u32 instr); void truncws(u32 instr); void truncwd(u32 instr); void truncls(u32 instr); void truncld(u32 instr); }; } // namespace n64