@@ -175,6 +175,7 @@ auto CPU::fpeUnimplemented() -> bool {
175
175
return true ;
176
176
}
177
177
178
+ template <bool CVT>
178
179
auto CPU::checkFPUExceptions () -> bool {
179
180
u32 exc = fenv.testExcept (float_env::divByZero
180
181
| float_env::inexact
@@ -183,6 +184,13 @@ auto CPU::checkFPUExceptions() -> bool {
183
184
| float_env::invalid);
184
185
if (!exc) return false ;
185
186
187
+ if constexpr (CVT) {
188
+ if (exc & float_env::invalid) {
189
+ if (fpeUnimplemented ()) exception .floatingPoint ();
190
+ return true ;
191
+ }
192
+ }
193
+
186
194
if (exc & float_env::underflow) {
187
195
if (!fpu.csr .flushSubnormals || fpu.csr .enable .underflow || fpu.csr .enable .inexact ) {
188
196
if (fpeUnimplemented ()) exception .floatingPoint ();
@@ -200,13 +208,16 @@ auto CPU::checkFPUExceptions() -> bool {
200
208
return raise ;
201
209
}
202
210
203
- #define CHECK_FPE (type, operation ) ({ \
211
+ #define CHECK_FPE_IMPL (type, operation, convert ) ({ \
204
212
fenv.clearExcept (); \
205
213
type res = [&]() noinline -> type { return operation; }(); \
206
- if (checkFPUExceptions ()) return ; \
214
+ if (checkFPUExceptions<convert> ()) return ; \
207
215
(res); \
208
216
})
209
217
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
+
210
221
auto f32repr (f32 f) -> n32 {
211
222
uint32_t v; memcpy (&v, &f, 4 );
212
223
return n32 (v);
@@ -444,15 +455,15 @@ auto CPU::FCEIL_W_S(u8 fd, u8 fs) -> void {
444
455
if (!fpuCheckStart ()) return ;
445
456
auto ffs = FS (f32);
446
457
if (!fpuCheckInputConv<s32>(ffs )) return ;
447
- auto ffd = CHECK_FPE (s32, roundCeil<s32>(ffs ));
458
+ auto ffd = CHECK_FPE_CONV (s32, roundCeil<s32>(ffs ));
448
459
FD (s32) = ffd;
449
460
}
450
461
451
462
auto CPU::FCEIL_W_D (u8 fd, u8 fs) -> void {
452
463
if (!fpuCheckStart ()) return ;
453
464
auto ffs = FS (f64);
454
465
if (!fpuCheckInputConv<s32>(ffs )) return ;
455
- auto ffd = CHECK_FPE (s32, roundCeil<s32>(ffs ));
466
+ auto ffd = CHECK_FPE_CONV (s32, roundCeil<s32>(ffs ));
456
467
FD (s32) = ffd;
457
468
}
458
469
@@ -719,15 +730,15 @@ auto CPU::FCVT_W_S(u8 fd, u8 fs) -> void {
719
730
if (!fpuCheckStart ()) return ;
720
731
auto ffs = FS (f32);
721
732
if (!fpuCheckInputConv<s32>(ffs )) return ;
722
- auto ffd = CHECK_FPE (s32, roundCurrent<s32>(ffs ));
733
+ auto ffd = CHECK_FPE_CONV (s32, roundCurrent<s32>(ffs ));
723
734
FD (s32) = ffd;
724
735
}
725
736
726
737
auto CPU::FCVT_W_D (u8 fd, u8 fs) -> void {
727
738
if (!fpuCheckStart ()) return ;
728
739
auto ffs = FS (f64);
729
740
if (!fpuCheckInputConv<s32>(ffs )) return ;
730
- auto ffd = CHECK_FPE (s32, roundCurrent<s32>(ffs ));
741
+ auto ffd = CHECK_FPE_CONV (s32, roundCurrent<s32>(ffs ));
731
742
FD (s32) = ffd;
732
743
}
733
744
@@ -771,15 +782,15 @@ auto CPU::FFLOOR_W_S(u8 fd, u8 fs) -> void {
771
782
if (!fpuCheckStart ()) return ;
772
783
auto ffs = FS (f32);
773
784
if (!fpuCheckInputConv<s32>(ffs )) return ;
774
- auto ffd = CHECK_FPE (s32, roundFloor<s32>(ffs ));
785
+ auto ffd = CHECK_FPE_CONV (s32, roundFloor<s32>(ffs ));
775
786
FD (s32) = ffd;
776
787
}
777
788
778
789
auto CPU::FFLOOR_W_D (u8 fd, u8 fs) -> void {
779
790
if (!fpuCheckStart ()) return ;
780
791
auto ffs = FS (f64);
781
792
if (!fpuCheckInputConv<s32>(ffs )) return ;
782
- auto ffd = CHECK_FPE (s32, roundFloor<s32>(ffs ));
793
+ auto ffd = CHECK_FPE_CONV (s32, roundFloor<s32>(ffs ));
783
794
FD (s32) = ffd;
784
795
}
785
796
@@ -853,7 +864,7 @@ auto CPU::FROUND_W_S(u8 fd, u8 fs) -> void {
853
864
if (!fpuCheckStart ()) return ;
854
865
auto ffs = FS (f32);
855
866
if (!fpuCheckInputConv<s32>(ffs )) return ;
856
- auto ffd = CHECK_FPE (s32, roundNearest<s32>(ffs ));
867
+ auto ffd = CHECK_FPE_CONV (s32, roundNearest<s32>(ffs ));
857
868
if (ffd != ffs && fpeInexact ()) return exception .floatingPoint ();
858
869
FD (s32) = ffd;
859
870
}
@@ -862,7 +873,7 @@ auto CPU::FROUND_W_D(u8 fd, u8 fs) -> void {
862
873
if (!fpuCheckStart ()) return ;
863
874
auto ffs = FS (f64);
864
875
if (!fpuCheckInputConv<s32>(ffs )) return ;
865
- auto ffd = CHECK_FPE (s32, roundNearest<s32>(ffs ));
876
+ auto ffd = CHECK_FPE_CONV (s32, roundNearest<s32>(ffs ));
866
877
if (ffd != ffs && fpeInexact ()) return exception .floatingPoint ();
867
878
FD (s32) = ffd;
868
879
}
@@ -927,7 +938,7 @@ auto CPU::FTRUNC_W_S(u8 fd, u8 fs) -> void {
927
938
if (!fpuCheckStart ()) return ;
928
939
auto ffs = FS (f32);
929
940
if (!fpuCheckInputConv<s32>(ffs )) return ;
930
- auto ffd = CHECK_FPE (s32, roundTrunc<s32>(ffs ));
941
+ auto ffd = CHECK_FPE_CONV (s32, roundTrunc<s32>(ffs ));
931
942
if ((f32)ffd != ffs && fpeInexact ()) return exception .floatingPoint ();
932
943
FD (s32) = ffd;
933
944
}
@@ -936,7 +947,7 @@ auto CPU::FTRUNC_W_D(u8 fd, u8 fs) -> void {
936
947
if (!fpuCheckStart ()) return ;
937
948
auto ffs = FS (f64);
938
949
if (!fpuCheckInputConv<s32>(ffs )) return ;
939
- auto ffd = CHECK_FPE (s32, roundTrunc<s32>(ffs ));
950
+ auto ffd = CHECK_FPE_CONV (s32, roundTrunc<s32>(ffs ));
940
951
if ((f64)ffd != ffs && fpeInexact ()) return exception .floatingPoint ();
941
952
FD (s32) = ffd;
942
953
}
0 commit comments