From 709d8a45bceb0dc12f4a0360565131c475042f45 Mon Sep 17 00:00:00 2001 From: cecio Date: Thu, 2 Jul 2026 21:43:43 +0200 Subject: [PATCH] rep movs* implementation --- src/striga/semantics.py | 2 ++ src/striga/x86/control.py | 10 ++++++ src/striga/x86/data.py | 71 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/striga/semantics.py b/src/striga/semantics.py index 01b3fea..6b4e566 100644 --- a/src/striga/semantics.py +++ b/src/striga/semantics.py @@ -63,6 +63,7 @@ class GPR(NamedTuple): "af": 4, "zf": 6, "sf": 7, + "df": 10, "of": 11, } @@ -123,6 +124,7 @@ def __init__(self, module: Module, *, verbose=False): "of": 8, "pf": 8, "af": 8, + "df": 8, } self.reg_types = { name: types.int_n(size) for name, size in self.reg_sizes.items() diff --git a/src/striga/x86/control.py b/src/striga/x86/control.py index c665bf0..f5f35a3 100644 --- a/src/striga/x86/control.py +++ b/src/striga/x86/control.py @@ -403,6 +403,16 @@ def clc(sem: Semantics): sem.flag_write("cf", sem.i1.constant(0)) +@semantic +def std(sem: Semantics): + sem.flag_write("df", sem.i1.constant(1)) + + +@semantic +def cld(sem: Semantics): + sem.flag_write("df", sem.i1.constant(0)) + + @semantic def int_(sem: Semantics): sem.ir.ret_void() diff --git a/src/striga/x86/data.py b/src/striga/x86/data.py index 996511c..8887946 100644 --- a/src/striga/x86/data.py +++ b/src/striga/x86/data.py @@ -1,6 +1,6 @@ -from capstone import CS_OP_REG -from llvm import lookup_intrinsic_id -from ..semantics import FLAGS, Semantics, semantic +from capstone import CS_OP_REG, CS_OP_MEM +from llvm import lookup_intrinsic_id, IntPredicate +from ..semantics import FLAGS, Semantics, Successor, semantic, _semantics @semantic @@ -168,3 +168,68 @@ def xchg(sem: Semantics): dst = sem.op_read(0) sem.op_write(0, src) sem.op_write(1, dst) + + +def _movs_step(sem: Semantics): + size = sem.insn.operands[0].size + sem.op_write(0, sem.op_read(1)) + df = sem.flag_read("df") + delta = sem.ir.select( + df, sem.const64(-size, sign_extend=True), sem.const64(size) + ) + sem.reg_write("rsi", sem.ir.add(sem.reg_read("rsi"), delta)) + sem.reg_write("rdi", sem.ir.add(sem.reg_read("rdi"), delta)) + + +@semantic +def movsb(sem: Semantics): + _movs_step(sem) + + +@semantic +def movsw(sem: Semantics): + _movs_step(sem) + + +@semantic +def movsq(sem: Semantics): + _movs_step(sem) + + +@semantic +def movsd(sem: Semantics): + if all(op.type == CS_OP_MEM for op in sem.insn.operands): + _movs_step(sem) + else: + mov(sem) + + +def _rep(sem: Semantics, step_fn): + addr = sem.insn.address + fallthrough = addr + sem.insn.size + check = sem.function.append_basic_block(f"rep_check_{addr:#x}") + body = sem.function.append_basic_block(f"rep_body_{addr:#x}") + exit_block = sem.get_or_create_block(fallthrough) + + sem.ir.br(check) + + with check.create_builder() as ir: + sem.ir = ir + cond = sem.ir.icmp(IntPredicate.NE, sem.reg_read("rcx"), sem.const64(0)) + sem.ir.cond_br(cond, body, exit_block) + + with body.create_builder() as ir: + sem.ir = ir + step_fn(sem) + sem.reg_write("rcx", sem.ir.sub(sem.reg_read("rcx"), sem.const64(1))) + sem.ir.br(check) + + return [Successor(addr, sem.const64(fallthrough))] + + +def _rep_movs(sem: Semantics): + return _rep(sem, _movs_step) + + +for _m in ("rep movsb", "rep movsw", "rep movsd", "rep movsq"): + _semantics[_m] = _rep_movs