From a00a54539d9124d8b376ee9cbeab355d99c9d163 Mon Sep 17 00:00:00 2001 From: iximeow Date: Fri, 11 Sep 2026 15:57:22 +0000 Subject: fix {s,u}xt{h,b}[16] using an immediate to describe their rotates --- CHANGELOG | 2 ++ src/armv7.rs | 6 ++++++ src/armv7/display.rs | 10 ++++++++++ src/armv7/thumb.rs | 4 ++-- tests/armv7/thumb.rs | 10 +++++++--- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7b35eaa..61e29c0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -25,6 +25,8 @@ * thumb2: support ARMv8 hints PACBTI, BTI, ESB, PAC, and AUT * thumb2: fix `mrc`, `mrc2` use of register number "15", which means apsr_nzcv, rather than pc +* thumb2: several instructions which decode an explicit rotate operand now do so + into a distinct Operand::Ror (sxth, uxth, stxb16, utxb16, sxtb, uxtb) * ARMv8: support thumb2 encoding of `Test Target` instruction, `Opcode::TT` (formatted as any of `tt`, `ttt`, `tta`, `ttat`) * ARMv8: formerly-coprocessor instructions have been defined into SIMD extensions, diff --git a/src/armv7.rs b/src/armv7.rs index 87b44f5..30a8960 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -775,6 +775,10 @@ pub enum Operand { BankedSPSR(Bank), /// a mask of bits for the `spsr` register. StatusRegMask(StatusRegMask), + /// a standalone rotate right by the specified amount. + /// + /// this typically applies equally to multiple operands; see `sxtah`, `uxtah`, etc. + Ror(u8), /// the `apsr` register. APSR, /// the `spsr` register. @@ -846,6 +850,8 @@ pub trait OperandVisitor { fn visit_banked_spsr(&mut self, bank: Bank) -> Result; /// process an operand that is some set of bits out of a status register. fn visit_status_reg_mask(&mut self, mask: StatusRegMask) -> Result; + /// process an operand that is a standalone rotate of other operands in the instruction. + fn visit_rotate(&mut self, amt: u8) -> Result; /// process an operand that is `APSR`. fn visit_apsr(&mut self) -> Result; /// process an operand that is `SPSR`. diff --git a/src/armv7/display.rs b/src/armv7/display.rs index 1398ce6..2d2a77c 100644 --- a/src/armv7/display.rs +++ b/src/armv7/display.rs @@ -357,6 +357,13 @@ impl crate::armv7::OperandVisitor for DisplayingOperandVisitor<' Ok(()) } + fn visit_rotate(&mut self, amt: u8) -> Result { + self.emit_shift_type(ShiftStyle::ROR)?; + self.f.write_char(' ')?; + self.f.write_prefixed_u16(amt as u16)?; + Ok(()) + } + fn visit_apsr(&mut self) -> Result { self.f.span_start_register(); self.f.write_fixed_size("apsr")?; @@ -1437,6 +1444,9 @@ impl super::Operand { Operand::StatusRegMask(mask) => { visitor.visit_status_reg_mask(mask) } + Operand::Ror(amt) => { + visitor.visit_rotate(amt) + } Operand::APSR => { visitor.visit_apsr() }, diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs index 4340e95..1d9d96a 100644 --- a/src/armv7/thumb.rs +++ b/src/armv7/thumb.rs @@ -2860,7 +2860,7 @@ pub fn decode_into::Address, ::Word>>(d Operand::Reg(Reg::from_u8(rd)), Operand::Reg(Reg::from_u8(rm)), if rotate != 0 { - Operand::Imm32(rotate as u32) + Operand::Ror(rotate as u8) } else { Operand::Nothing }, @@ -2886,7 +2886,7 @@ pub fn decode_into::Address, ::Word>>(d Operand::Reg(Reg::from_u8(rn)), Operand::Reg(Reg::from_u8(rm)), if rotate != 0 { - Operand::Imm32(rotate as u32) + Operand::Ror(rotate as u8) } else { Operand::Nothing }, diff --git a/tests/armv7/thumb.rs b/tests/armv7/thumb.rs index 1278bd6..f03b046 100644 --- a/tests/armv7/thumb.rs +++ b/tests/armv7/thumb.rs @@ -4526,11 +4526,11 @@ fn test_decode_ux_sx_32b_cases() { ); test_display( &[0x5f, 0xfa, 0x9c, 0xfc], - "uxtb.w ip, ip, 0x8" + "uxtb.w ip, ip, ror 0x8" ); test_display( &[0x1f, 0xfa, 0xab, 0xfb], - "uxth.w fp, fp, 0x10" + "uxth.w fp, fp, ror 0x10" ); test_display( &[0x0f, 0xfa, 0x82, 0xf1], @@ -4538,13 +4538,17 @@ fn test_decode_ux_sx_32b_cases() { ); test_display( &[0x52, 0xfa, 0x93, 0xf1], - "uxtab.w r1, r2, r3, 0x8" + "uxtab.w r1, r2, r3, ror 0x8" ); test_display( &[0x42, 0xfa, 0x83, 0xf1], "sxtab.w r1, r2, r3" ); test_display( + &[0x2f, 0xfa, 0xfb, 0xf9], + "sxtb16.w sb, fp, ror 0x18" + ); + test_display( &[0x02, 0xfa, 0x83, 0xf1], "sxtah.w r1, r2, r3" ); -- cgit v1.1