@@ -79,6 +79,25 @@ mod int_to_float {
7979 F :: from_bits ( conv ( i. unsigned_abs ( ) ) | sign_bit)
8080 }
8181
82+ pub fn u32_to_f16_bits ( i : u32 ) -> u16 {
83+ let n = i. leading_zeros ( ) ;
84+ let i_m = i. wrapping_shl ( n) ;
85+ // Mantissa with implicit bit set
86+ let m_base: u16 = ( i_m >> shift_f_lt_i :: < u32 , f16 > ( ) ) as u16 ;
87+ // The entire lower half of `i` will be truncated (masked portion), plus the
88+ // next `EXPONENT_BITS` bits.
89+ let adj = ( i_m >> f16:: EXPONENT_BITS | i_m & 0xFF ) as u16 ;
90+ let m = m_adj :: < f16 > ( m_base, adj) ;
91+ let e = if i == 0 { 0 } else { exp :: < u32 , f16 > ( n) - 1 } ;
92+ // Any int can have an exponent out of range for `f16`, unlike other float types.
93+ // Clamp this.
94+ if e >= f16:: EXPONENT_MAX as u16 - 1 {
95+ f16:: INFINITY . to_bits ( )
96+ } else {
97+ repr :: < f16 > ( e, m)
98+ }
99+ }
100+
82101 pub fn u32_to_f32_bits ( i : u32 ) -> u32 {
83102 if i == 0 {
84103 return 0 ;
@@ -122,6 +141,32 @@ mod int_to_float {
122141 ( h as u128 ) << 64
123142 }
124143
144+ pub fn u64_to_f16_bits ( i : u64 ) -> u16 {
145+ let n = i. leading_zeros ( ) ;
146+ let i_m = i. wrapping_shl ( n) ; // Mantissa, shifted so the first bit is nonzero
147+ let m_base: u16 = ( i_m >> shift_f_lt_i :: < u64 , f16 > ( ) ) as u16 ;
148+
149+ // Within the upper `F::BITS`, everything except for the signifcand
150+ // gets truncated
151+ let d1: u16 = ( i_m >> ( u64:: BITS - f16:: BITS - f16:: SIGNIFICAND_BITS - 1 ) ) . cast ( ) ;
152+
153+ // The entire rest of `i_m` gets truncated. Zero the upper `F::BITS` then just
154+ // check if it is nonzero.
155+ let d2: u16 = ( i_m << f16:: BITS >> f16:: BITS != 0 ) . into ( ) ;
156+ let adj = d1 | d2;
157+
158+ // Mantissa with implicit bit set
159+ let m = m_adj :: < f16 > ( m_base, adj) ;
160+ let e = if i == 0 { 0 } else { exp :: < u64 , f16 > ( n) - 1 } ;
161+
162+ // Clamp to infinity if the exponent is out of range
163+ if e >= f16:: EXPONENT_MAX as u16 - 1 {
164+ f16:: INFINITY . to_bits ( )
165+ } else {
166+ repr :: < f16 > ( e, m)
167+ }
168+ }
169+
125170 pub fn u64_to_f32_bits ( i : u64 ) -> u32 {
126171 let n = i. leading_zeros ( ) ;
127172 let i_m = i. wrapping_shl ( n) ;
@@ -160,6 +205,32 @@ mod int_to_float {
160205 repr :: < f128 > ( e, m)
161206 }
162207
208+ pub fn u128_to_f16_bits ( i : u128 ) -> u16 {
209+ let n = i. leading_zeros ( ) ;
210+ let i_m = i. wrapping_shl ( n) ; // Mantissa, shifted so the first bit is nonzero
211+ let m_base: u16 = ( i_m >> shift_f_lt_i :: < u128 , f16 > ( ) ) as u16 ;
212+
213+ // Within the upper `F::BITS`, everything except for the signifcand
214+ // gets truncated
215+ let d1: u16 = ( i_m >> ( u128:: BITS - f16:: BITS - f16:: SIGNIFICAND_BITS - 1 ) ) . cast ( ) ;
216+
217+ // The entire rest of `i_m` gets truncated. Zero the upper `F::BITS` then just
218+ // check if it is nonzero.
219+ let d2: u16 = ( i_m << f16:: BITS >> f16:: BITS != 0 ) . into ( ) ;
220+ let adj = d1 | d2;
221+
222+ // Mantissa with implicit bit set
223+ let m = m_adj :: < f16 > ( m_base, adj) ;
224+ let e = if i == 0 { 0 } else { exp :: < u128 , f16 > ( n) - 1 } ;
225+
226+ // Clamp to infinity if the exponent is out of range
227+ if e >= f16:: EXPONENT_MAX as u16 - 1 {
228+ f16:: INFINITY . to_bits ( )
229+ } else {
230+ repr :: < f16 > ( e, m)
231+ }
232+ }
233+
163234 pub fn u128_to_f32_bits ( i : u128 ) -> u32 {
164235 let n = i. leading_zeros ( ) ;
165236 let i_m = i. wrapping_shl ( n) ; // Mantissa, shifted so the first bit is nonzero
@@ -210,6 +281,11 @@ mod int_to_float {
210281
211282// Conversions from unsigned integers to floats.
212283intrinsics ! {
284+ #[ cfg( f16_enabled) ]
285+ pub extern "C" fn __floatunsihf( i: u32 ) -> f16 {
286+ f16:: from_bits( int_to_float:: u32_to_f16_bits( i) )
287+ }
288+
213289 #[ arm_aeabi_alias = __aeabi_ui2f]
214290 pub extern "C" fn __floatunsisf( i: u32 ) -> f32 {
215291 f32 :: from_bits( int_to_float:: u32_to_f32_bits( i) )
@@ -220,6 +296,17 @@ intrinsics! {
220296 f64 :: from_bits( int_to_float:: u32_to_f64_bits( i) )
221297 }
222298
299+ #[ ppc_alias = __floatunsikf]
300+ #[ cfg( f128_enabled) ]
301+ pub extern "C" fn __floatunsitf( i: u32 ) -> f128 {
302+ f128:: from_bits( int_to_float:: u32_to_f128_bits( i) )
303+ }
304+
305+ #[ cfg( f16_enabled) ]
306+ pub extern "C" fn __floatundihf( i: u64 ) -> f16 {
307+ f16:: from_bits( int_to_float:: u64_to_f16_bits( i) )
308+ }
309+
223310 #[ arm_aeabi_alias = __aeabi_ul2f]
224311 pub extern "C" fn __floatundisf( i: u64 ) -> f32 {
225312 f32 :: from_bits( int_to_float:: u64_to_f32_bits( i) )
@@ -230,6 +317,17 @@ intrinsics! {
230317 f64 :: from_bits( int_to_float:: u64_to_f64_bits( i) )
231318 }
232319
320+ #[ ppc_alias = __floatundikf]
321+ #[ cfg( f128_enabled) ]
322+ pub extern "C" fn __floatunditf( i: u64 ) -> f128 {
323+ f128:: from_bits( int_to_float:: u64_to_f128_bits( i) )
324+ }
325+
326+ #[ cfg( f16_enabled) ]
327+ pub extern "C" fn __floatuntihf( i: u128 ) -> f16 {
328+ f16:: from_bits( int_to_float:: u128_to_f16_bits( i) )
329+ }
330+
233331 #[ cfg_attr( target_os = "uefi" , unadjusted_on_win64) ]
234332 pub extern "C" fn __floatuntisf( i: u128 ) -> f32 {
235333 f32 :: from_bits( int_to_float:: u128_to_f32_bits( i) )
@@ -240,18 +338,6 @@ intrinsics! {
240338 f64 :: from_bits( int_to_float:: u128_to_f64_bits( i) )
241339 }
242340
243- #[ ppc_alias = __floatunsikf]
244- #[ cfg( f128_enabled) ]
245- pub extern "C" fn __floatunsitf( i: u32 ) -> f128 {
246- f128:: from_bits( int_to_float:: u32_to_f128_bits( i) )
247- }
248-
249- #[ ppc_alias = __floatundikf]
250- #[ cfg( f128_enabled) ]
251- pub extern "C" fn __floatunditf( i: u64 ) -> f128 {
252- f128:: from_bits( int_to_float:: u64_to_f128_bits( i) )
253- }
254-
255341 #[ ppc_alias = __floatuntikf]
256342 #[ cfg( f128_enabled) ]
257343 pub extern "C" fn __floatuntitf( i: u128 ) -> f128 {
@@ -261,6 +347,11 @@ intrinsics! {
261347
262348// Conversions from signed integers to floats.
263349intrinsics ! {
350+ #[ cfg( f16_enabled) ]
351+ pub extern "C" fn __floatsihf( i: i32 ) -> f16 {
352+ int_to_float:: signed( i, int_to_float:: u32_to_f16_bits)
353+ }
354+
264355 #[ arm_aeabi_alias = __aeabi_i2f]
265356 pub extern "C" fn __floatsisf( i: i32 ) -> f32 {
266357 int_to_float:: signed( i, int_to_float:: u32_to_f32_bits)
@@ -271,6 +362,17 @@ intrinsics! {
271362 int_to_float:: signed( i, int_to_float:: u32_to_f64_bits)
272363 }
273364
365+ #[ ppc_alias = __floatsikf]
366+ #[ cfg( f128_enabled) ]
367+ pub extern "C" fn __floatsitf( i: i32 ) -> f128 {
368+ int_to_float:: signed( i, int_to_float:: u32_to_f128_bits)
369+ }
370+
371+ #[ cfg( f16_enabled) ]
372+ pub extern "C" fn __floatdihf( i: i64 ) -> f16 {
373+ int_to_float:: signed( i, int_to_float:: u64_to_f16_bits)
374+ }
375+
274376 #[ arm_aeabi_alias = __aeabi_l2f]
275377 pub extern "C" fn __floatdisf( i: i64 ) -> f32 {
276378 int_to_float:: signed( i, int_to_float:: u64_to_f32_bits)
@@ -281,6 +383,17 @@ intrinsics! {
281383 int_to_float:: signed( i, int_to_float:: u64_to_f64_bits)
282384 }
283385
386+ #[ ppc_alias = __floatdikf]
387+ #[ cfg( f128_enabled) ]
388+ pub extern "C" fn __floatditf( i: i64 ) -> f128 {
389+ int_to_float:: signed( i, int_to_float:: u64_to_f128_bits)
390+ }
391+
392+ #[ cfg( f16_enabled) ]
393+ pub extern "C" fn __floattihf( i: i128 ) -> f16 {
394+ int_to_float:: signed( i, int_to_float:: u128_to_f16_bits)
395+ }
396+
284397 #[ cfg_attr( target_os = "uefi" , unadjusted_on_win64) ]
285398 pub extern "C" fn __floattisf( i: i128 ) -> f32 {
286399 int_to_float:: signed( i, int_to_float:: u128_to_f32_bits)
@@ -291,18 +404,6 @@ intrinsics! {
291404 int_to_float:: signed( i, int_to_float:: u128_to_f64_bits)
292405 }
293406
294- #[ ppc_alias = __floatsikf]
295- #[ cfg( f128_enabled) ]
296- pub extern "C" fn __floatsitf( i: i32 ) -> f128 {
297- int_to_float:: signed( i, int_to_float:: u32_to_f128_bits)
298- }
299-
300- #[ ppc_alias = __floatdikf]
301- #[ cfg( f128_enabled) ]
302- pub extern "C" fn __floatditf( i: i64 ) -> f128 {
303- int_to_float:: signed( i, int_to_float:: u64_to_f128_bits)
304- }
305-
306407 #[ ppc_alias = __floattikf]
307408 #[ cfg( f128_enabled) ]
308409 pub extern "C" fn __floattitf( i: i128 ) -> f128 {
0 commit comments