Skip to content

Commit ceecf8d

Browse files
committed
core: Add ARM64 FJCVTZS instruction optimization for f64 to i32
1 parent 7ab3548 commit ceecf8d

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

core/src/ecma_conversions.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,47 @@ 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).
4242
pub fn f64_to_wrapping_i32(n: f64) -> i32 {
43+
#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
44+
{
45+
// macOS aarch64 always has jsconv feature
46+
// SAFETY: macOS aarch64 always supports jsconv
47+
unsafe { f64_to_int32_arm64(n) }
48+
}
49+
#[cfg(all(target_arch = "aarch64", not(target_os = "macos")))]
50+
{
51+
if std::arch::is_aarch64_feature_detected!("jsconv") {
52+
// SAFETY: Feature detection confirmed jsconv is available
53+
unsafe { f64_to_int32_arm64(n) }
54+
} else {
55+
f64_to_int32_generic(n)
56+
}
57+
}
58+
#[cfg(not(target_arch = "aarch64"))]
59+
{
60+
f64_to_int32_generic(n)
61+
}
62+
}
63+
64+
fn f64_to_wrapping_i32_generic(n: f64) -> i32 {
4365
f64_to_wrapping_u32(n) as i32
4466
}
4567

68+
#[cfg(target_arch = "aarch64")]
69+
#[target_feature(enable = "jsconv")]
70+
/// Converts an `f64` to an `i32` with ECMAScript `ToInt32` wrapping behavior.
71+
/// The value will be wrapped in the range [-2^31, 2^31).
72+
/// Optimized for macOS aarch64 with the fjcvtzs instruction.
73+
unsafe fn f64_to_int32_arm64(number: f64) -> i32 {
74+
let ret: i32;
75+
// SAFETY: fjcvtzs instruction is available on macOS aarch64.
76+
std::arch::asm!(
77+
"fjcvtzs {dst:w}, {src:d}",
78+
src = in(vreg) number,
79+
dst = out(reg) ret,
80+
);
81+
ret
82+
}
83+
4684
/// Implements the IEEE-754 "Round to nearest, ties to even" rounding rule.
4785
/// (e.g., both 1.5 and 2.5 will round to 2).
4886
/// This also clamps out-of-range values and NaN to `i32::MIN`.

0 commit comments

Comments
 (0)