commit d03fc7006031c9dc5eed4db9b0f9d01ada2cbd7e
parent 5c94996fc63c8005b8eba620933adf31620e82c6
Author: Jared Tobin <jared@jtobin.io>
Date: Sun, 17 May 2026 20:54:44 -0230
parser: accept shifted-immediate operand form
AArch64 allows immediates with an optional `, lsl #n` (or lsr/asr)
suffix, e.g. `cmp x8, #16, lsl #12`. The operand parser was
falling through to `pImm`, leaving `, lsl #12` unconsumed and
producing a parse error.
Add `pImmShifted` (used only in operand position) which folds the
trailing shift into the literal value (e.g. 16 << 12 = 65536).
Other call sites of `pImm` (Movz/Movk/Movn, addressing modes,
Svc) are unchanged.
Diffstat:
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/lib/Audit/AArch64/Parser.hs b/lib/Audit/AArch64/Parser.hs
@@ -398,18 +398,43 @@ pOperand :: Parser Operand
pOperand = choice
[ try (OpAddr <$> pAddrMode)
, try pRegOrShiftedReg
- , OpImm <$> pImm
+ , OpImm <$> pImmShifted
, OpLabel <$> pSymbolRef
]
--- Parse register once, then optionally check for shift suffix.
+-- | Like pImm but accepts the AArch64 shifted-immediate form
+-- (e.g., @#16, lsl #12@) and folds the shift into the value.
+-- Only LSL/LSR/ASR by an explicit amount are recognised.
+pImmShifted :: Parser Integer
+pImmShifted = do
+ n <- pImm
+ mSh <- optional (try (pComma *> pImmShiftOp))
+ pure $ case mSh of
+ Nothing -> n
+ Just (op, k) -> case op of
+ ShL -> n * (2 ^ k)
+ ShR -> n `div` (2 ^ k) -- LSR on a literal: arithmetic floor div
+ ShA -> n `div` (2 ^ k) -- ASR likewise (sign preserved by div)
+
+data ImmShiftOp = ShL | ShR | ShA
+
+pImmShiftOp :: Parser (ImmShiftOp, Int)
+pImmShiftOp = lexeme $ choice
+ [ (,) ShL <$> (string' "lsl" *> sc *> pShiftAmt)
+ , (,) ShR <$> (string' "lsr" *> sc *> pShiftAmt)
+ , (,) ShA <$> (string' "asr" *> sc *> pShiftAmt)
+ ]
+
+-- Parse register once, then optionally check for
+-- shift or extend suffix.
pRegOrShiftedReg :: Parser Operand
pRegOrShiftedReg = do
r <- pReg
- mShift <- optional (pComma *> pShift)
- pure $ case mShift of
- Just sh -> OpShiftedReg r sh
- Nothing -> OpReg r
+ mMod <- optional (pComma *> pShiftOrExtend)
+ pure $ case mMod of
+ Just (Left sh) -> OpShiftedReg r sh
+ Just (Right ex) -> OpExtendedReg r ex
+ Nothing -> OpReg r
pImm :: Parser Integer
pImm = lexeme $ do