diff options
| author | iximeow <me@iximeow.net> | 2026-09-11 16:57:56 +0000 |
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2026-09-11 16:57:56 +0000 |
| commit | 9eebd279e4a523e009150786ca270f0e2330e0c3 (patch) | |
| tree | 6c8ff475a50518e0a165fbb750ea840b26b79ec0 | |
| parent | 475321a686f346ac51cded60384a903fa8e9fdf8 (diff) | |
report rounding bit of smmla/smmls
| -rw-r--r-- | CHANGELOG | 2 | ||||
| -rw-r--r-- | src/armv7.rs | 2 | ||||
| -rw-r--r-- | src/armv7/display.rs | 4 | ||||
| -rw-r--r-- | src/armv7/thumb.rs | 56 | ||||
| -rw-r--r-- | tests/armv7/thumb.rs | 8 |
5 files changed, 58 insertions, 14 deletions
@@ -36,6 +36,8 @@ the field is 1-based rather than 0-based, so for example an instruction which had that operand as "1" was incorrectly decoded as being "0" * thumb2: fix `hvc` immediate missing its upper four bits +* thumb2: report "round" bit of `smmls` and `smmla` (as the new `smmlsr` and + `smmlar` opcodes) * ARMv7: do not try to elide memory offset when 0 in postindex operands. this makes a post-index (and implied writeback!) ambiguous with a pre-indexed access with offset zero. that is, `[r1, 0]` may be written as `[r1]`, but diff --git a/src/armv7.rs b/src/armv7.rs index 30a8960..537dccd 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -257,7 +257,9 @@ pub enum Opcode { SMLSD, SMMLA, + SMMLAR, SMMLS, + SMMLSR, USADA8, USAD8, SMLAD, diff --git a/src/armv7/display.rs b/src/armv7/display.rs index 3f7162b..7b0be82 100644 --- a/src/armv7/display.rs +++ b/src/armv7/display.rs @@ -858,7 +858,9 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for ConditionedOpcode { Opcode::UMLAL | Opcode::SMLSD | Opcode::SMMLA | + Opcode::SMMLAR | Opcode::SMMLS | + Opcode::SMMLSR | Opcode::USADA8 | Opcode::USAD8 | Opcode::SDIV | @@ -1185,7 +1187,9 @@ impl Opcode { Opcode::SMLSLD(false) => { "smlsldb" }, Opcode::SMLSD => { "smlsd" }, Opcode::SMMLA => { "smmla" }, + Opcode::SMMLAR => { "smmlar" }, Opcode::SMMLS => { "smmls" }, + Opcode::SMMLSR => { "smmlsr" }, Opcode::USADA8 => { "usada8" }, Opcode::USAD8 => { "usad8" }, Opcode::SMLAD => { "smlad" }, diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs index 96b6b98..b59754c 100644 --- a/src/armv7/thumb.rs +++ b/src/armv7/thumb.rs @@ -3228,6 +3228,23 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d Operand::Reg(Reg::from_u8(rm)), Operand::Nothing, ]; + } else if op1 == 0b110 { + // Ra == 0b1111? unpredictable! + decoder.unpredictable()?; + if op2 >= 0b10 { + return Err(DecodeError::InvalidOpcode); + } + if op2 == 0b00 { + inst.opcode = Opcode::SMMLS; + } else { + inst.opcode = Opcode::SMMLSR; + } + inst.operands = [ + Operand::Reg(Reg::from_u8(rd)), + Operand::Reg(Reg::from_u8(rn)), + Operand::Reg(Reg::from_u8(rm)), + Operand::Reg(Reg::from_u8(ra)), + ]; } else { if op2 >= 0b10 { return Err(DecodeError::InvalidOpcode); @@ -3235,9 +3252,6 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d if op1 == 0b111 && op2 == 0b00 { return Err(DecodeError::InvalidOpcode); } - if op1 == 0b110 { - decoder.unpredictable()?; - } inst.opcode = [ Opcode::MUL, // already handled Opcode::UDF, // already handled @@ -3245,7 +3259,7 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d Opcode::UDF, // already handled Opcode::SMUSD, Opcode::SMMUL, - Opcode::SMMLS, + Opcode::SMMLS, // already handled Opcode::USAD8, ][op1]; inst.operands = [ @@ -3291,6 +3305,35 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d Operand::Reg(Reg::from_u8(rm)), Operand::Reg(Reg::from_u8(ra)), ]; + } else if op1 == 0b110 { + if op2 >= 0b10 { + return Err(DecodeError::InvalidOpcode); + } + if op2 == 0b00 { + inst.opcode = Opcode::SMMLS; + } else { + inst.opcode = Opcode::SMMLSR; + } + inst.operands = [ + Operand::Reg(Reg::from_u8(rd)), + Operand::Reg(Reg::from_u8(rn)), + Operand::Reg(Reg::from_u8(rm)), + Operand::Reg(Reg::from_u8(ra)), + ]; + } else if op1 == 0b101 { + if op2 == 0b00 { + inst.opcode = Opcode::SMMLA; + } else if op2 == 0b01 { + inst.opcode = Opcode::SMMLAR; + } else { + return Err(DecodeError::InvalidOpcode); + } + inst.operands = [ + Operand::Reg(Reg::from_u8(rd)), + Operand::Reg(Reg::from_u8(rn)), + Operand::Reg(Reg::from_u8(rm)), + Operand::Reg(Reg::from_u8(ra)), + ]; } else { if op2 >= 0b10 { return Err(DecodeError::InvalidOpcode); @@ -3298,9 +3341,6 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d if op1 == 0b111 && op2 == 0b00 { return Err(DecodeError::InvalidOpcode); } - if op1 == 0b110 { - decoder.unpredictable()?; - } inst.opcode = [ Opcode::MUL, // already handled Opcode::UDF, // already handled @@ -3308,7 +3348,7 @@ pub fn decode_into<T: Reader<<ARMv7 as Arch>::Address, <ARMv7 as Arch>::Word>>(d Opcode::UDF, // already handled Opcode::SMLSD, Opcode::SMMLA, - Opcode::SMMLS, + Opcode::SMMLS, // already handled Opcode::USADA8, ][op1]; inst.operands = [ diff --git a/tests/armv7/thumb.rs b/tests/armv7/thumb.rs index 6b8c891..ed9ae0e 100644 --- a/tests/armv7/thumb.rs +++ b/tests/armv7/thumb.rs @@ -4699,15 +4699,11 @@ fn smml() { // smmla, smmlar, smmls, smmlsr test_display( &[0x64, 0xfb, 0x1f, 0x92], - "smmlsr r2, r4, pc, sb" + "smmlsr.w r2, r4, pc, sb" ); test_display( &[0x59, 0xfb, 0x1b, 0x66], - "smmlar r6, sb, fp, r6" - ); - test_display( - &[0x20, 0xfb, 0x1d, 0xd1], - "smladx r1, r0, sp, sp" + "smmlar.w r6, sb, fp, r6" ); } |
