diff --git a/crates/aarch64/src/lib.rs b/crates/aarch64/src/lib.rs index bbef3be..22ee0ac 100644 --- a/crates/aarch64/src/lib.rs +++ b/crates/aarch64/src/lib.rs @@ -49,6 +49,7 @@ const NEON_COMPARE_UNSIGNED_HIGHER_USER_OP: &str = "NEON_cmhi"; const NEON_COMPARE_GREATER_THAN_OR_EQUAL_USER_OP: &str = "NEON_cmge"; const NEON_COMPARE_GREATER_THAN_USER_OP: &str = "NEON_cmgt"; const NEON_BITWISE_INSERT_USER_OP: &str = "NEON_bit"; +const NEON_BITWISE_INSERT_IF_FALSE_USER_OP: &str = "NEON_bif"; const NEON_MINIMUM_NUMBER_USER_OP: &str = "NEON_fminnm"; const NEON_FUSED_MULTIPLY_ADD_USER_OP: &str = "NEON_fmadd"; const NEON_ROUND_INTEGRAL_USER_OP: &str = "NEON_frint"; @@ -1226,13 +1227,11 @@ fn lower_control_pcode( right: lower_value(language, right)?, element_size: arguments[0]?, }), - NEON_BITWISE_INSERT_USER_OP => Some(Operation::NeonBitwiseInsert { - destination: lower_place(language, output)?, - original: lower_value(language, left)?, - source: lower_value(language, right)?, - mask: arguments[0]?, - element_size: arguments[1]?, - }), + NEON_BITWISE_INSERT_USER_OP | NEON_BITWISE_INSERT_IF_FALSE_USER_OP => { + lower_neon_bitwise_insert_pcode( + language, user_op, output, left, right, arguments, + ) + } NEON_UNSIGNED_MULTIPLY_LONG_USER_OP => Some(Operation::NeonUnsignedMultiplyLong { destination: lower_place(language, output)?, left: lower_value(language, left)?, @@ -1246,6 +1245,28 @@ fn lower_control_pcode( } } +fn lower_neon_bitwise_insert_pcode( + language: &SleighData, + user_op: &str, + output: VarNode, + left: PcodeValue, + right: PcodeValue, + arguments: [Option; 2], +) -> Option { + let (original, source) = if user_op == NEON_BITWISE_INSERT_IF_FALSE_USER_OP { + (right, left) + } else { + (left, right) + }; + Some(Operation::NeonBitwiseInsert { + destination: lower_place(language, output)?, + original: lower_value(language, original)?, + source: lower_value(language, source)?, + mask: arguments[0]?, + element_size: arguments[1]?, + }) +} + fn is_extended_user_op(user_op: &str) -> bool { matches!( user_op, @@ -4401,6 +4422,9 @@ mod tests { const BITWISE_INSERT: &[u8] = &[ 0x40, 0x1c, 0xa1, 0x6e, // bit v0.16b, v2.16b, v1.16b ]; + const BITWISE_INSERT_IF_FALSE: &[u8] = &[ + 0xe2, 0x1c, 0xf1, 0x6e, // bif v2.16b, v7.16b, v17.16b + ]; let mut memory = executable_memory(CODE); let mut state = Aarch64State::new(CODE_ADDRESS, GuestAddress::new(0x8000)); state @@ -4467,6 +4491,17 @@ mod tests { state.set_vector(2, 0xaaaa_aaaa_aaaa_aaaa).unwrap(); interpreter.step(&mut state, &mut memory).unwrap(); assert_eq!(state.vector(0), Some(0xaa0f_aa0f_aa0f_aa0f)); + + let mut memory = executable_memory(BITWISE_INSERT_IF_FALSE); + let mut state = Aarch64State::new(CODE_ADDRESS, GuestAddress::new(0x8000)); + let original = 0x0123_4567_89ab_cdef_fedc_ba98_7654_3210; + let source = 0xf0f0_f0f0_0f0f_0f0f_aaaa_5555_ffff_0000; + let mask = 0xff00_ff00_ff00_ff00_00ff_00ff_00ff_00ff; + state.set_vector(2, original).unwrap(); + state.set_vector(7, source).unwrap(); + state.set_vector(17, mask).unwrap(); + interpreter.step(&mut state, &mut memory).unwrap(); + assert_eq!(state.vector(2), Some((original & mask) | (source & !mask))); } #[test]