Skip to content

Commit 4e36ce7

Browse files
invertegoLukeUsher
authored andcommitted
n64: raise unimpl instead of invalid for fpu conversions
1 parent ba862a2 commit 4e36ce7

File tree

2 files changed

+24
-13
lines changed

2 files changed

+24
-13
lines changed

ares/n64/cpu/cpu.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ struct CPU : Thread {
656656
template<typename T> auto fgr(u32) -> T&;
657657
auto getControlRegisterFPU(n5) -> u32;
658658
auto setControlRegisterFPU(n5, n32) -> void;
659-
auto checkFPUExceptions() -> bool;
659+
template<bool CVT> auto checkFPUExceptions() -> bool;
660660
auto fpeDivisionByZero() -> bool;
661661
auto fpeInexact() -> bool;
662662
auto fpeUnderflow() -> bool;

ares/n64/cpu/interpreter-fpu.cpp

+23-12
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ auto CPU::fpeUnimplemented() -> bool {
175175
return true;
176176
}
177177

178+
template<bool CVT>
178179
auto CPU::checkFPUExceptions() -> bool {
179180
u32 exc = fenv.testExcept(float_env::divByZero
180181
| float_env::inexact
@@ -183,6 +184,13 @@ auto CPU::checkFPUExceptions() -> bool {
183184
| float_env::invalid);
184185
if (!exc) return false;
185186

187+
if constexpr(CVT) {
188+
if(exc & float_env::invalid) {
189+
if(fpeUnimplemented()) exception.floatingPoint();
190+
return true;
191+
}
192+
}
193+
186194
if(exc & float_env::underflow) {
187195
if(!fpu.csr.flushSubnormals || fpu.csr.enable.underflow || fpu.csr.enable.inexact) {
188196
if(fpeUnimplemented()) exception.floatingPoint();
@@ -200,13 +208,16 @@ auto CPU::checkFPUExceptions() -> bool {
200208
return raise;
201209
}
202210

203-
#define CHECK_FPE(type, operation) ({ \
211+
#define CHECK_FPE_IMPL(type, operation, convert) ({ \
204212
fenv.clearExcept(); \
205213
type res = [&]() noinline -> type { return operation; }(); \
206-
if (checkFPUExceptions()) return; \
214+
if (checkFPUExceptions<convert>()) return; \
207215
(res); \
208216
})
209217

218+
#define CHECK_FPE(type, operation) CHECK_FPE_IMPL(type, operation, false)
219+
#define CHECK_FPE_CONV(type, operation) CHECK_FPE_IMPL(type, operation, true)
220+
210221
auto f32repr(f32 f) -> n32 {
211222
uint32_t v; memcpy(&v, &f, 4);
212223
return n32(v);
@@ -444,15 +455,15 @@ auto CPU::FCEIL_W_S(u8 fd, u8 fs) -> void {
444455
if(!fpuCheckStart()) return;
445456
auto ffs = FS(f32);
446457
if(!fpuCheckInputConv<s32>(ffs)) return;
447-
auto ffd = CHECK_FPE(s32, roundCeil<s32>(ffs));
458+
auto ffd = CHECK_FPE_CONV(s32, roundCeil<s32>(ffs));
448459
FD(s32) = ffd;
449460
}
450461

451462
auto CPU::FCEIL_W_D(u8 fd, u8 fs) -> void {
452463
if(!fpuCheckStart()) return;
453464
auto ffs = FS(f64);
454465
if(!fpuCheckInputConv<s32>(ffs)) return;
455-
auto ffd = CHECK_FPE(s32, roundCeil<s32>(ffs));
466+
auto ffd = CHECK_FPE_CONV(s32, roundCeil<s32>(ffs));
456467
FD(s32) = ffd;
457468
}
458469

@@ -719,15 +730,15 @@ auto CPU::FCVT_W_S(u8 fd, u8 fs) -> void {
719730
if(!fpuCheckStart()) return;
720731
auto ffs = FS(f32);
721732
if(!fpuCheckInputConv<s32>(ffs)) return;
722-
auto ffd = CHECK_FPE(s32, roundCurrent<s32>(ffs));
733+
auto ffd = CHECK_FPE_CONV(s32, roundCurrent<s32>(ffs));
723734
FD(s32) = ffd;
724735
}
725736

726737
auto CPU::FCVT_W_D(u8 fd, u8 fs) -> void {
727738
if(!fpuCheckStart()) return;
728739
auto ffs = FS(f64);
729740
if(!fpuCheckInputConv<s32>(ffs)) return;
730-
auto ffd = CHECK_FPE(s32, roundCurrent<s32>(ffs));
741+
auto ffd = CHECK_FPE_CONV(s32, roundCurrent<s32>(ffs));
731742
FD(s32) = ffd;
732743
}
733744

@@ -771,15 +782,15 @@ auto CPU::FFLOOR_W_S(u8 fd, u8 fs) -> void {
771782
if(!fpuCheckStart()) return;
772783
auto ffs = FS(f32);
773784
if(!fpuCheckInputConv<s32>(ffs)) return;
774-
auto ffd = CHECK_FPE(s32, roundFloor<s32>(ffs));
785+
auto ffd = CHECK_FPE_CONV(s32, roundFloor<s32>(ffs));
775786
FD(s32) = ffd;
776787
}
777788

778789
auto CPU::FFLOOR_W_D(u8 fd, u8 fs) -> void {
779790
if(!fpuCheckStart()) return;
780791
auto ffs = FS(f64);
781792
if(!fpuCheckInputConv<s32>(ffs)) return;
782-
auto ffd = CHECK_FPE(s32, roundFloor<s32>(ffs));
793+
auto ffd = CHECK_FPE_CONV(s32, roundFloor<s32>(ffs));
783794
FD(s32) = ffd;
784795
}
785796

@@ -853,7 +864,7 @@ auto CPU::FROUND_W_S(u8 fd, u8 fs) -> void {
853864
if(!fpuCheckStart()) return;
854865
auto ffs = FS(f32);
855866
if(!fpuCheckInputConv<s32>(ffs)) return;
856-
auto ffd = CHECK_FPE(s32, roundNearest<s32>(ffs));
867+
auto ffd = CHECK_FPE_CONV(s32, roundNearest<s32>(ffs));
857868
if(ffd != ffs && fpeInexact()) return exception.floatingPoint();
858869
FD(s32) = ffd;
859870
}
@@ -862,7 +873,7 @@ auto CPU::FROUND_W_D(u8 fd, u8 fs) -> void {
862873
if(!fpuCheckStart()) return;
863874
auto ffs = FS(f64);
864875
if(!fpuCheckInputConv<s32>(ffs)) return;
865-
auto ffd = CHECK_FPE(s32, roundNearest<s32>(ffs));
876+
auto ffd = CHECK_FPE_CONV(s32, roundNearest<s32>(ffs));
866877
if(ffd != ffs && fpeInexact()) return exception.floatingPoint();
867878
FD(s32) = ffd;
868879
}
@@ -927,7 +938,7 @@ auto CPU::FTRUNC_W_S(u8 fd, u8 fs) -> void {
927938
if(!fpuCheckStart()) return;
928939
auto ffs = FS(f32);
929940
if(!fpuCheckInputConv<s32>(ffs)) return;
930-
auto ffd = CHECK_FPE(s32, roundTrunc<s32>(ffs));
941+
auto ffd = CHECK_FPE_CONV(s32, roundTrunc<s32>(ffs));
931942
if((f32)ffd != ffs && fpeInexact()) return exception.floatingPoint();
932943
FD(s32) = ffd;
933944
}
@@ -936,7 +947,7 @@ auto CPU::FTRUNC_W_D(u8 fd, u8 fs) -> void {
936947
if(!fpuCheckStart()) return;
937948
auto ffs = FS(f64);
938949
if(!fpuCheckInputConv<s32>(ffs)) return;
939-
auto ffd = CHECK_FPE(s32, roundTrunc<s32>(ffs));
950+
auto ffd = CHECK_FPE_CONV(s32, roundTrunc<s32>(ffs));
940951
if((f64)ffd != ffs && fpeInexact()) return exception.floatingPoint();
941952
FD(s32) = ffd;
942953
}

0 commit comments

Comments
 (0)