From 038ee0e9129f69e49ec97c8b685a0e0515fff21c Mon Sep 17 00:00:00 2001 From: Corbin Crutchley Date: Sat, 25 Jul 2026 23:14:21 -0700 Subject: [PATCH] fix: clear upper lanes after SIMD reductions --- crates/aarch64/src/lib.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/crates/aarch64/src/lib.rs b/crates/aarch64/src/lib.rs index 86a2127..bbef3be 100644 --- a/crates/aarch64/src/lib.rs +++ b/crates/aarch64/src/lib.rs @@ -2299,6 +2299,7 @@ fn execute_neon_value_operation( let maximum = matches!(operation, Operation::NeonUnsignedMaximumAcross { .. }); let result = unsigned_lane_extreme(read(source)?, source.size, element_size, maximum) .ok_or_else(unsupported)?; + let destination = scalar_vector_destination(destination).ok_or_else(unsupported)?; Ok((destination, result)) } Operation::NeonUnsignedMaximumPairwise { @@ -2765,9 +2766,27 @@ fn execute_neon_byte_reduction( result = result.wrapping_add(byte); } } + let destination = if count_bits { + destination + } else { + scalar_vector_destination(destination).ok_or_else(unsupported)? + }; Ok((destination, result)) } +fn scalar_vector_destination(destination: Place) -> Option { + match destination { + Place { + storage: Storage::Vector { offset: 0, .. }, + size: 1..=16, + } => Some(Place { + storage: destination.storage, + size: 16, + }), + _ => None, + } +} + fn execute_neon_unsigned_multiply_long( state: &Aarch64State, scratch: &ScratchValues, @@ -4352,6 +4371,7 @@ mod tests { let upper = 0xfeed_face_cafe_beef_u128 << 64; let mut state = Aarch64State::new(CODE_ADDRESS, GuestAddress::new(0x8000)); state.set_vector(0, upper | 0x0103_070f_1f3f_7fff).unwrap(); + state.set_vector(22, u128::MAX).unwrap(); for _ in 0..RUST_VECTOR_COUNT_CODE.len() / 4 { interpreter.step(&mut state, &mut memory).unwrap(); } @@ -4401,10 +4421,7 @@ mod tests { state.vector(1), Some(u128::from(u32::MAX) << 96 | u128::from(u32::MAX) << 32) ); - assert_eq!( - state.vector(2), - Some(vector_two_upper | u128::from(u32::MAX)) - ); + assert_eq!(state.vector(2), Some(u128::from(u32::MAX))); let mut memory = executable_memory(SELECT_AND_MINIMUM); let mut state = Aarch64State::new(CODE_ADDRESS, GuestAddress::new(0x8000)); @@ -4415,7 +4432,7 @@ mod tests { for _ in 0..2 { interpreter.step(&mut state, &mut memory).unwrap(); } - assert_eq!(state.vector(0), Some(upper | 0xaa11_aa11_aa11_aa11)); + assert_eq!(state.vector(0), Some(0xaa11)); let mut memory = executable_memory(ZERO_COMPARE); let mut state = Aarch64State::new(CODE_ADDRESS, GuestAddress::new(0x8000)); -- 2.51.2