Skip to content

Add semantics for adc, ror, shld, shrd, rcl, rcr#3

Open
idkfrancis wants to merge 2 commits into
LLVMParty:masterfrom
idkfrancis:feat/adc-ror-shld-shrd-rcl-rcr
Open

Add semantics for adc, ror, shld, shrd, rcl, rcr#3
idkfrancis wants to merge 2 commits into
LLVMParty:masterfrom
idkfrancis:feat/adc-ror-shld-shrd-rcl-rcr

Conversation

@idkfrancis

Copy link
Copy Markdown

Adds lifters for six x86 integer instructions encountered while lifting obfuscated VM handlers. All semantics follow the Intel SDM Vol 2 pseudocode and reuse the existing helpers (masked_shift_count, flag_undef, flag_write_if, result_sign_bit, result_parity_even, result_is_zero, add_overflow, write_common_arith_flags).

Instructions

  • ADCDEST + SRC + CF. CF detects unsigned overflow with carry-in (ULT(result, dst) OR (EQ(result, dst) AND cf_in)). OF uses the standard add-overflow formula on (dst, src, result) — this stays correct under carry-in because cf_in is a low-position addend and does not affect the sign-bit XOR pattern.
  • ROR — rotate right. CF is the MSB of the result. For 1-bit rotates, OF is the XOR of the two most-significant bits of the result; undefined otherwise.
  • SHLD / SHRD — double-precision shift left/right. Implemented via a 2*width-bit concatenation (dst:src for SHLD, src:dst for SHRD) shifted by count. CF is the last bit shifted out of dst. PF/ZF/SF/AF and the OF-on-1-bit case are handled by a shared double_shift_flags helper.
  • RCL / RCR — rotate through carry. Implemented via a (width+1)-bit concatenation packing CF as the high bit. The effective rotation count is count % (width + 1). New CF is the high bit of the rotated wide value. For 1-bit RCL, OF = MSB(result) XOR new_CF (post-rotation per SDM); for 1-bit RCR, OF = MSB(dst) XOR cf_in (pre-rotation per SDM).

All instructions zero-update flags only when the masked count is non-zero, matching the existing SHL/SHR/SAR/ROL pattern. Stub semantics for instructions where state is not tracked (e.g. STD/CLD, RDTSC, string ops) are intentionally not part of this PR.

Verification

  • uv run lift.py runs to completion against the existing sample binaries with no errors (14480 lines of IR emitted).
  • Each instruction was sanity-checked against the Intel SDM Vol 2 pseudocode and worked examples for boundary cases (count = 0, count = 1, count = width, ADC with src == 0xFF and cf == 1).

tests/x86_ops.asm assembles to a 1.5KB PE whose entry point uses each
new opcode (ADC, ROR, SHLD, SHRD, RCL, RCR) in its imm, register and
CL-count forms across 8/16/32/64-bit widths. lift.py picks it up at
0x140001000 so the CI smoke test now dispatches into the new code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant