@@ -31,66 +31,13 @@ namespace SST::RevCPU {
31
31
32
32
struct RevInst ;
33
33
34
- // Mappings from floating point to same-sized integer types
35
- template <typename T>
36
- struct uint_type {};
37
-
38
- template <>
39
- struct uint_type <double > {
40
- using type = uint64_t ;
41
- static_assert ( sizeof ( type ) == sizeof ( double ) );
42
- };
43
-
44
- template <>
45
- struct uint_type <float > {
46
- using type = uint32_t ;
47
- static_assert ( sizeof ( type ) == sizeof ( float ) );
48
- };
49
-
50
- template <>
51
- struct uint_type <float16> {
52
- using type = uint16_t ;
53
- static_assert ( sizeof ( type ) == sizeof ( float16 ) );
54
- };
55
-
56
- template <typename T>
57
- using uint_type_t = typename uint_type<T>::type;
58
-
59
- // / BoxNaN: Store a boxed floating point value inside a possibly larger one
60
- template <typename T, typename U, typename = std::enable_if_t <sizeof ( T ) >= sizeof ( U )>>
61
- inline void BoxNaN ( T* dest, const U* value ) {
62
- if constexpr ( sizeof ( T ) == sizeof ( U ) ) {
63
- *dest = *value;
64
- } else {
65
- uint_type_t <U> i;
66
- memcpy ( &i, value, sizeof ( i ) ); // The value
67
- uint_type_t <T> box = uint_type_t <T>{ i } | ~uint_type_t <T>{ 0 } << sizeof ( U ) * 8 ; // Boxed NaN value
68
- memcpy ( dest, &box, sizeof ( box ) ); // Store in larger register
69
- static_assert ( sizeof ( i ) == sizeof ( U ) && sizeof ( box ) == sizeof ( T ) );
70
- }
71
- }
72
-
73
- // / UnBoxNaN: Unbox a floating point value into a possibly smaller one
74
- // The second argument indicates whether it is a FMV/FS move/store
75
- // instruction which just transfers bits and not care about NaN-Boxing.
76
- template <typename T, bool FMV_FS = false , typename U, typename = std::enable_if_t <sizeof ( T ) <= sizeof ( U )>>
77
- inline T UnBoxNaN ( const U* val ) {
78
- if constexpr ( sizeof ( T ) == sizeof ( U ) ) {
79
- return *val;
80
- } else {
81
- uint_type_t <U> i;
82
- memcpy ( &i, val, sizeof ( i ) );
83
- static_assert ( sizeof ( i ) == sizeof ( val ) );
84
- T fp;
85
- if ( !FMV_FS && ~i >> sizeof ( T ) * 8 ) {
86
- fp = std::numeric_limits<T>::quiet_NaN ();
87
- } else {
88
- auto ifp = static_cast <uint_type_t <T>>( i );
89
- memcpy ( &fp, &ifp, sizeof ( fp ) );
90
- static_assert ( sizeof ( ifp ) == sizeof ( fp ) );
91
- }
92
- return fp;
93
- }
34
+ // / BoxNaN: Store a boxed float inside a double
35
+ inline void BoxNaN ( double * dest, const float * value ) {
36
+ uint32_t i32;
37
+ memcpy ( &i32, value, sizeof ( i32 ) ); // The FP32 value
38
+ uint64_t i64 = uint64_t { i32 } | ~uint64_t { 0 } << 32 ; // Boxed NaN value
39
+ memcpy ( dest, &i64, sizeof ( i64 ) ); // Store in FP64 register
40
+ static_assert ( sizeof ( i32 ) == sizeof ( float ) && sizeof ( i64 ) == sizeof ( double ) );
94
41
}
95
42
96
43
// / RISC-V Register Mneumonics
@@ -356,23 +303,34 @@ class RevRegFile {
356
303
template <typename T, bool FMV_FS = false , typename U>
357
304
T GetFP ( U rs ) const {
358
305
if constexpr ( std::is_same_v<T, double > ) {
359
- return DPF[size_t ( rs )];
360
- } else if ( HasD ) {
361
- return UnBoxNaN<T, FMV_FS>( &DPF[size_t ( rs )] );
306
+ return DPF[size_t ( rs )]; // The FP64 register's value
362
307
} else {
363
- return UnBoxNaN<T, FMV_FS>( &SPF[size_t ( rs )] );
308
+ float fp32;
309
+ if ( !HasD ) {
310
+ fp32 = SPF[size_t ( rs )]; // The FP32 register's value
311
+ } else {
312
+ uint64_t i64;
313
+ memcpy ( &i64, &DPF[size_t ( rs )], sizeof ( i64 ) ); // The FP64 register's value
314
+ if ( !FMV_FS && ~i64 >> 32 ) { // Check for boxed NaN unless FMV/FS
315
+ fp32 = NAN; // Return NaN if it's not boxed
316
+ } else {
317
+ auto i32 = static_cast <uint32_t >( i64 ); // For endian independence on host
318
+ memcpy ( &fp32, &i32, sizeof ( fp32 ) ); // The bottom half of FP64
319
+ }
320
+ }
321
+ return fp32; // Reinterpreted as FP32
364
322
}
365
323
}
366
324
367
325
// / SetFP: Set a specific FP register to a floating-point value
368
326
template <typename T, typename U>
369
327
void SetFP ( U rd, T value ) {
370
328
if constexpr ( std::is_same_v<T, double > ) {
371
- DPF[size_t ( rd )] = value;
329
+ DPF[size_t ( rd )] = value; // Store in FP64 register
372
330
} else if ( HasD ) {
373
- BoxNaN ( &DPF[size_t ( rd )], &value );
331
+ BoxNaN ( &DPF[size_t ( rd )], &value ); // Store NaN-boxed float in FP64 register
374
332
} else {
375
- BoxNaN ( & SPF[size_t ( rd )], &value );
333
+ SPF[size_t ( rd )] = value; // Store in FP32 register
376
334
}
377
335
}
378
336
@@ -467,8 +425,8 @@ class RevRegFile {
467
425
FCSR& GetFCSR () { return fcsr; }
468
426
469
427
// Friend functions and classes to access internal register state
470
- template <typename INT , typename FP >
471
- friend bool fcvtif ( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst );
428
+ template <typename FP , typename INT >
429
+ friend bool CvtFpToInt ( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst );
472
430
473
431
template <typename T>
474
432
friend bool load ( RevFeature* F, RevRegFile* R, RevMem* M, const RevInst& Inst );
0 commit comments