diff options
| author | Grond <grond@grondhaus.net> | 2026-06-24 14:11:18 -0700 |
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2026-07-28 02:53:24 +0000 |
| commit | 44f91bf710081d98b465252487a6b168b2f2597e (patch) | |
| tree | 4a345f7574fc83ccfa7d4fe7a757e39eacf2eb93 /src | |
| parent | 40743d84ffc8bbe0a4e24b9af4d65d58a1367b23 (diff) | |
Implement the RRX immediate shift type
Diffstat (limited to 'src')
| -rw-r--r-- | src/armv7.rs | 39 | ||||
| -rw-r--r-- | src/armv7/display.rs | 33 |
2 files changed, 49 insertions, 23 deletions
diff --git a/src/armv7.rs b/src/armv7.rs index f911388..ada486a 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -331,6 +331,10 @@ pub enum ShiftStyle { ASR = 2, /// rotate-right, filling with bits shifted out of the value. ROR = 3, + /// shift right by one, populating the new most-significant bit from the carry flag. + /// + /// only possible on immediate shifts. + RRX = 4, } impl Display for ShiftStyle { @@ -345,7 +349,7 @@ impl Display for ShiftStyle { } impl ShiftStyle { - fn from(bits: u8) -> ShiftStyle { + fn from_bits(bits: u8) -> ShiftStyle { match bits { 0b00 => ShiftStyle::LSL, 0b01 => ShiftStyle::LSR, @@ -357,10 +361,11 @@ impl ShiftStyle { fn name(&self) -> &'static [u8; 3] { match self { - ShiftStyle::LSL => &[b'l', b's', b'l'], - ShiftStyle::LSR => &[b'l', b's', b'r'], - ShiftStyle::ASR => &[b'a', b's', b'r'], - ShiftStyle::ROR => &[b'r', b'o', b'r'], + ShiftStyle::LSL => b"lsl", + ShiftStyle::LSR => b"lsr", + ShiftStyle::ASR => b"asr", + ShiftStyle::ROR => b"ror", + ShiftStyle::RRX => b"rrx", } } } @@ -372,7 +377,7 @@ impl RegRegShift { } /// the way in which this register is shifted. pub fn stype(&self) -> ShiftStyle { - ShiftStyle::from((self.data >> 5) as u8 & 0b11) + ShiftStyle::from_bits((self.data >> 5) as u8 & 0b11) } /// the general-purpose register to be shifted. pub fn shiftee(&self) -> Reg { @@ -387,9 +392,14 @@ pub struct RegImmShift { } impl RegImmShift { + /// The shift immediate, without any interpretation + fn imm_raw(&self) -> u8 { + (self.data >> 7) as u8 & 0b11111 + } + /// the immediate this register is shifted by. pub fn imm(&self) -> u8 { - let raw = (self.data >> 7) as u8 & 0b11111; + let raw = self.imm_raw(); // in the ARMv7m reference, // `Instruction Details` -> // `Shifts applied to a register` -> @@ -403,12 +413,18 @@ impl RegImmShift { // > ASR #<n> type = 0b10 // > If <n> < 32, immediate = <n>. // > If <n> == 32, immediate = 0. + // > ... + // > ROR #<n> type = 0b11, immediate = <n>. + // > RRX type = 0b11, immediate = 0. // // so we have to fix this up here. if raw == 0 { let stype = self.stype(); if stype == ShiftStyle::LSR || stype == ShiftStyle::ASR { return 32; + } else if stype == ShiftStyle::ROR { + // this is actually RRX, which rotates by exactly one bit. + return 1; } } raw @@ -416,8 +432,15 @@ impl RegImmShift { /// the way in which this register is shifted. pub fn stype(&self) -> ShiftStyle { - ShiftStyle::from((self.data >> 5) as u8 & 0b11) + let stype = ShiftStyle::from_bits((self.data >> 5) as u8 & 0b11); + + if self.imm_raw() == 0 && stype == ShiftStyle::ROR { + ShiftStyle::RRX + } else { + stype + } } + /// the general-purpose register to be shifted. pub fn shiftee(&self) -> Reg { Reg::from_u8(self.data as u8 & 0b1111) diff --git a/src/armv7/display.rs b/src/armv7/display.rs index 5ceedd6..29d3ed6 100644 --- a/src/armv7/display.rs +++ b/src/armv7/display.rs @@ -97,22 +97,25 @@ impl<T: DisplaySink> DisplayingOperandVisitor<'_, T> { match shift.into_shift() { RegShiftStyle::RegImm(imm_shift) => { self.f.write_reg(imm_shift.shiftee().number())?; - if imm_shift.imm() != 0 || imm_shift.stype() != ShiftStyle::LSL { + let stype = imm_shift.stype(); + if imm_shift.imm() != 0 || stype != ShiftStyle::LSL { self.f.write_fixed_size(", ")?; - self.emit_shift_type(imm_shift.stype())?; - self.f.write_char(' ')?; - let sh = imm_shift.imm(); - if sh >= 30 { - self.f.write_char('3')?; - self.f.write_char((sh - 30 + 0x30) as char)?; - } else if sh >= 20 { - self.f.write_char('2')?; - self.f.write_char((sh - 20 + 0x30) as char)?; - } else if sh >= 10 { - self.f.write_char('1')?; - self.f.write_char((sh - 10 + 0x30) as char)?; - } else { - self.f.write_char((sh + 0x30) as char)?; + self.emit_shift_type(stype)?; + if stype != ShiftStyle::RRX { + self.f.write_char(' ')?; + let sh = imm_shift.imm(); + if sh >= 30 { + self.f.write_char('3')?; + self.f.write_char((sh - 30 + 0x30) as char)?; + } else if sh >= 20 { + self.f.write_char('2')?; + self.f.write_char((sh - 20 + 0x30) as char)?; + } else if sh >= 10 { + self.f.write_char('1')?; + self.f.write_char((sh - 10 + 0x30) as char)?; + } else { + self.f.write_char((sh + 0x30) as char)?; + } } } } |
