Skip to content

AArch64: keep the Rm operand of the register-form shifts - #3063

Open
gaul wants to merge 1 commit into
capstone-engine:nextfrom
gaul:aarch64-shift-reg-rm-operand
Open

AArch64: keep the Rm operand of the register-form shifts#3063
gaul wants to merge 1 commit into
capstone-engine:nextfrom
gaul:aarch64-shift-reg-rm-operand

Conversation

@gaul

@gaul gaul commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Your checklist for this pull request

  • I've documented or updated the documentation of every API function and struct this PR changes.
  • I've added tests that prove my fix is effective or that my feature works (if possible)

Detailed description

The register-form variable shifts -- LSLV/LSRV/ASRV/RORV, printed lsl/lsr/asr/ror with a register amount -- were generated with only two detail operands. add_non_alias_details() folds the shift amount Rm into the preceding operand's shift.value (with an AARCH64_SFT_*_REG type) to describe the shift, and then called AArch64_dec_op_count(), dropping Rm from the operand list entirely:

  ror w0, w1, w2
  op_count: 2
    operands[0].type: REG = w0            access: WRITE
    operands[1].type: REG = w1            access: READ
                      shift: ROR_REG w2

A consumer walking the operand list therefore never saw w2, the shift amount and a genuine read. cs_regs_access() still reported it -- the shift-value harvest at the bottom of AArch64_reg_access() reads shift.value back as a register -- so, exactly as with the STLUR Rt bug (#3046), only the operand view was broken.

Drop the dec_op_count() so Rm stays in the list as the third operand it prints as. The shift annotation on operand 1 is kept, so no information is lost; AArch64_reg_access() de-duplicates the restored operand against the shift-value read via arr_exist(), so the reported register lists do not change. The printed text is rendered from the MCInst and was never affected.

Test plan

Extends the four existing per-mnemonic regression cases (and their three duplicates) with the restored operand, and adds the 64-bit forms as new coverage.

Closing issues

The register-form variable shifts -- LSLV/LSRV/ASRV/RORV, printed
lsl/lsr/asr/ror with a register amount -- were generated with only two
detail operands. add_non_alias_details() folds the shift amount Rm into
the preceding operand's shift.value (with an AARCH64_SFT_*_REG type) to
describe the shift, and then called AArch64_dec_op_count(), dropping Rm
from the operand list entirely:

  ror w0, w1, w2
  op_count: 2
    operands[0].type: REG = w0            access: WRITE
    operands[1].type: REG = w1            access: READ
                      shift: ROR_REG w2

A consumer walking the operand list therefore never saw w2, the shift
amount and a genuine read. cs_regs_access() still reported it -- the
shift-value harvest at the bottom of AArch64_reg_access() reads
shift.value back as a register -- so, exactly as with the STLUR Rt bug
(capstone-engine#3046), only the operand view was broken.

Drop the dec_op_count() so Rm stays in the list as the third operand it
prints as. The shift annotation on operand 1 is kept, so no information
is lost; AArch64_reg_access() de-duplicates the restored operand against
the shift-value read via arr_exist(), so the reported register lists do
not change. The printed text is rendered from the MCInst and was never
affected.

Extends the four existing per-mnemonic regression cases (and their three
duplicates) with the restored operand, and adds the 64-bit forms as new
coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the AArch64 Arch label Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant