Skip to content

Commit 261a837

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

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ egui = ["dep:egui", "dep:egui_extras", "png"]
9292
jpegxr = ["dep:jpegxr", "lzma"]
9393
default_font = []
9494
serde = ["serde/derive"]
95+
aarch64_jsconv = []
9596

9697
[build-dependencies]
9798
build_playerglobal = { path = "build_playerglobal" }

core/src/ecma_conversions.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,44 @@ 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(feature = "aarch64_jsconv")]
44+
{
45+
#[cfg(all(target_arch = "aarch64", target_feature = "jsconv"))]
46+
unsafe {
47+
f64_to_wrapping_int32_aarch64(n)
48+
}
49+
#[cfg(not(all(target_arch = "aarch64", target_feature = "jsconv")))]
50+
f64_to_wrapping_i32_generic(n)
51+
}
52+
#[cfg(not(feature = "aarch64_jsconv"))]
53+
f64_to_wrapping_i32_generic(n)
54+
}
55+
56+
#[allow(unused)]
57+
fn f64_to_wrapping_i32_generic(n: f64) -> i32 {
4358
f64_to_wrapping_u32(n) as i32
4459
}
4560

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

0 commit comments

Comments
 (0)