@@ -40,9 +40,57 @@ pub fn f64_to_wrapping_u32(n: f64) -> u32 {
4040/// Converts an `f64` to an `i32` with ECMAScript `ToInt32` wrapping behavior.
4141/// The value will be wrapped in the range [-2^31, 2^31).
4242pub fn f64_to_wrapping_i32 ( n : f64 ) -> i32 {
43+ // TODO: use core intrinsic when https://github.com/rust-lang/rust/issues/147555 is stabilized.
44+ #[ cfg( target_arch = "aarch64" ) ]
45+ {
46+ #[ cfg( target_feature = "jsconv" ) ]
47+ // SAFETY: `jsconv` feature is checked in compile time to be existed, so it's safe to call.
48+ unsafe {
49+ f64_to_wrapping_int32_aarch64 ( n)
50+ }
51+ #[ cfg( not( target_feature = "jsconv" ) ) ]
52+ if std:: arch:: is_aarch64_feature_detected!( "jsconv" ) {
53+ // SAFETY: `jsconv` feature is checked in runtime to be existed, so it's safe to call.
54+ unsafe { f64_to_wrapping_int32_aarch64 ( n) }
55+ } else {
56+ f64_to_wrapping_i32_generic ( n)
57+ }
58+ }
59+ #[ cfg( not( target_arch = "aarch64" ) ) ]
60+ f64_to_wrapping_i32_generic ( n)
61+ }
62+
63+ #[ allow( unused) ]
64+ fn f64_to_wrapping_i32_generic ( n : f64 ) -> i32 {
4365 f64_to_wrapping_u32 ( n) as i32
4466}
4567
68+ /// Converts an `f64` to an `i32` with ECMAScript `ToInt32` wrapping behavior.
69+ /// The value will be wrapped in the range [-2^31, 2^31).
70+ /// Optimized for aarch64 cpu with the fjcvtzs instruction.
71+ ///
72+ /// # Safety
73+ ///
74+ /// The caller must ensure either:
75+ /// - The target platform is aarch64 with `jsconv` feature enabled, or
76+ /// - Runtime feature detection has been performed to verify `jsconv` support
77+ #[ allow( unused) ]
78+ #[ cfg( target_arch = "aarch64" ) ]
79+ #[ target_feature( enable = "jsconv" ) ]
80+ unsafe fn f64_to_wrapping_int32_aarch64 ( number : f64 ) -> i32 {
81+ let ret: i32 ;
82+ // SAFETY: fjcvtzs instruction is available under jsconv feature.
83+ unsafe {
84+ std:: arch:: asm!(
85+ "fjcvtzs {dst:w}, {src:d}" ,
86+ src = in( vreg) number,
87+ dst = out( reg) ret,
88+ options( nostack, nomem, pure)
89+ ) ;
90+ }
91+ ret
92+ }
93+
4694/// Implements the IEEE-754 "Round to nearest, ties to even" rounding rule.
4795/// (e.g., both 1.5 and 2.5 will round to 2).
4896/// This also clamps out-of-range values and NaN to `i32::MIN`.
0 commit comments