@@ -40,9 +40,53 @@ 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+ #[ cfg( target_arch = "aarch64" ) ]
44+ #[ cfg( target_feature = "jsconv" ) ]
45+ {
46+ // macOS aarch64 always has jsconv feature
47+ // SAFETY: macOS aarch64 always supports jsconv
48+ unsafe { f64_to_wrapping_int32_arm64 ( n) }
49+ }
50+ #[ cfg( target_arch = "aarch64" ) ]
51+ #[ cfg( not( target_feature = "jsconv" ) ) ]
52+ {
53+ if std:: arch:: is_aarch64_feature_detected!( "jsconv" ) {
54+ // SAFETY: Feature detection confirmed jsconv is available
55+ unsafe { f64_to_wrapping_int32_arm64 ( n) }
56+ } else {
57+ f64_to_wrapping_i32_generic ( n)
58+ }
59+ }
60+ #[ cfg( not( target_arch = "aarch64" ) ) ]
61+ {
62+ f64_to_wrapping_i32_generic ( n)
63+ }
64+ }
65+
66+ #[ allow( unused) ]
67+ fn f64_to_wrapping_i32_generic ( n : f64 ) -> i32 {
4368 f64_to_wrapping_u32 ( n) as i32
4469}
4570
71+ #[ allow( unused) ]
72+ #[ cfg( target_arch = "aarch64" ) ]
73+ #[ target_feature( enable = "jsconv" ) ]
74+ /// Converts an `f64` to an `i32` with ECMAScript `ToInt32` wrapping behavior.
75+ /// The value will be wrapped in the range [-2^31, 2^31).
76+ /// Optimized for macOS aarch64 with the fjcvtzs instruction.
77+ unsafe fn f64_to_wrapping_int32_arm64 ( number : f64 ) -> i32 {
78+ let ret: i32 ;
79+ // SAFETY: fjcvtzs instruction is available on macOS aarch64.
80+ unsafe {
81+ std:: arch:: asm!(
82+ "fjcvtzs {dst:w}, {src:d}" ,
83+ src = in( vreg) number,
84+ dst = out( reg) ret,
85+ ) ;
86+ }
87+ ret
88+ }
89+
4690/// Implements the IEEE-754 "Round to nearest, ties to even" rounding rule.
4791/// (e.g., both 1.5 and 2.5 will round to 2).
4892/// This also clamps out-of-range values and NaN to `i32::MIN`.
0 commit comments