diff options
| -rw-r--r-- | src/armv7/display.rs | 11 | ||||
| -rw-r--r-- | src/armv7/thumb.rs | 9 | ||||
| -rw-r--r-- | tests/armv7/thumb.rs | 22 |
3 files changed, 36 insertions, 6 deletions
diff --git a/src/armv7/display.rs b/src/armv7/display.rs index 6f6fba1..d2198de 100644 --- a/src/armv7/display.rs +++ b/src/armv7/display.rs @@ -620,8 +620,15 @@ pub(crate) fn visit_inst<T: DisplaySink>(instr: &Instruction, out: &mut T) -> fm panic!("impossible it operand"); }; - let inv = cond & 1 == 1; - let condition = ConditionCode::build(*cond as u8); + let (inv, condition) = if *cond == 0b1111 { + // we've allowed *unpredictable* instruction encodings. capstone calls this condition + // "al" as well, so might as well follow along... and for this condition code it + // doesn't invert the fields either! + (false, ConditionCode::AL) + } else { + let inv = cond & 1 == 1; + (inv, ConditionCode::build(*cond as u8)) + }; if mask & 0b0001 != 0 { // three flags out.write_char(if inv ^ ((mask & 0b1000) != 0) { 'e' } else { 't' })?; diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs index 7aa3a5d..9e9c30a 100644 --- a/src/armv7/thumb.rs +++ b/src/armv7/thumb.rs @@ -3918,8 +3918,13 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d let firstcond = opa; let mask = opb; inst.opcode = Opcode::IT; - if firstcond == 0b1111 { - return Err(DecodeError::InvalidOperand); + if decoder.should_is_must { + // > if firstcond == ‘1111’ || + // > (firstcond == ‘1110’ && BitCount(mask) != 1) + // > then UNPREDICTABLE; + if firstcond == 0b1111 { + return Err(DecodeError::Nonconforming); + } } inst.operands = [ Operand::Imm32(firstcond), diff --git a/tests/armv7/thumb.rs b/tests/armv7/thumb.rs index d9ecda6..c8b0b11 100644 --- a/tests/armv7/thumb.rs +++ b/tests/armv7/thumb.rs @@ -19,8 +19,8 @@ fn test_invalid_under(decoder: &InstDecoder, data: &[u8]) { } #[allow(dead_code)] -fn test_display_under(decoder: &InstDecoder, data: [u8; 4], expected: &'static str) { - let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); +fn test_display_under(decoder: &InstDecoder, data: &[u8], expected: &'static str) { + let mut reader = yaxpeax_arch::U8Reader::new(data); let instr = match decoder.decode(&mut reader) { Err(e) => { panic!("failed to decode {:#x?}: {}", data, e) @@ -76,6 +76,20 @@ fn test_display(data: &[u8], expected: &'static str) { ); } +fn test_nonconforming(data: &[u8], expected: &'static str) { + let conforming = InstDecoder::default_thumb().allow_nonconforming(false); + let nonconforming = InstDecoder::default_thumb().allow_nonconforming(true); + + let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); + let result = conforming.decode(&mut reader); + assert!( + result.is_err(), + "got bad result: {:?} from {:#x?}", result, data + ); + + test_display_under(&nonconforming, data, expected); +} + #[test] fn test_unpredictable_instructions() { test_invalid(&[0x80, 0xfa, 0x40, 0x00]); @@ -1951,6 +1965,10 @@ fn test_decode_it_cases() { &[0xef, 0xbf], "iteee al" ); + test_nonconforming( + &[0xf7, 0xbf], + "ittee al", + ); } #[test] fn test_decode_ldm_16b_cases() { |
