diff options
| author | Grond <grond@grondhaus.net> | 2026-06-23 14:02:51 -0700 |
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2026-07-28 02:53:24 +0000 |
| commit | 40743d84ffc8bbe0a4e24b9af4d65d58a1367b23 (patch) | |
| tree | 3e6f4a789bda85fc5334ea682c5c2686494fab80 /src/armv7.rs | |
| parent | 1bff2519a50ac4e3ca98b4d874f70c02628c3f4a (diff) | |
Fix the handling of arithmetic register shifts with zero immediates
Diffstat (limited to 'src/armv7.rs')
| -rw-r--r-- | src/armv7.rs | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/src/armv7.rs b/src/armv7.rs index 2ce8122..f911388 100644 --- a/src/armv7.rs +++ b/src/armv7.rs @@ -389,8 +389,31 @@ pub struct RegImmShift { impl RegImmShift { /// the immediate this register is shifted by. pub fn imm(&self) -> u8 { - (self.data >> 7) as u8 & 0b11111 + let raw = (self.data >> 7) as u8 & 0b11111; + // in the ARMv7m reference, + // `Instruction Details` -> + // `Shifts applied to a register` -> + // `Constant shifts`: + // + // > The assembler encodes <shift> into two type bits and five immediate bits, as follows: + // > ... + // > LSR #<n> type = 0b01 + // > If <n> < 32, immediate = <n>. + // > If <n> == 32, immediate = 0. + // > ASR #<n> type = 0b10 + // > If <n> < 32, immediate = <n>. + // > If <n> == 32, 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; + } + } + raw } + /// the way in which this register is shifted. pub fn stype(&self) -> ShiftStyle { ShiftStyle::from((self.data >> 5) as u8 & 0b11) |
