github.com/decomp/exp@v0.0.0-20210624183419-6d058f5e1da6/lift/x86/term_loopcc.go (about)

     1  package x86
     2  
     3  import (
     4  	"github.com/decomp/exp/disasm/x86"
     5  	"github.com/llir/llvm/ir/constant"
     6  	"github.com/llir/llvm/ir/enum"
     7  	"github.com/llir/llvm/ir/types"
     8  	"golang.org/x/arch/x86/x86asm"
     9  )
    10  
    11  // Loop According to ECX Counter
    12  //
    13  //    (ECX≠0)            LOOP     Loop if ECX register is not zero.
    14  //    (ECX≠0 and ZF=1)   LOOPE    Loop if equal and ECX register is not zero.
    15  //    (ECX≠0 and ZF=0)   LOOPNE   Loop if not equal and ECX register is not zero.
    16  //
    17  // ref: $ 3.2 LOOP/LOOPcc - Loop According to ECX Counter, Intel 64 and IA-32
    18  // Architectures Software Developer's Manual
    19  
    20  // --- [ LOOP ] ----------------------------------------------------------------
    21  
    22  // liftTermLOOP lifts the given x86 LOOP instruction to LLVM IR, emitting code
    23  // to f.
    24  func (f *Func) liftTermLOOP(term *x86.Inst) error {
    25  	// Loop if ECX register is not zero.
    26  	//    (ECX≠0)
    27  	ecx := f.dec(x86.NewArg(x86asm.ECX, term))
    28  	zero := constant.NewInt(types.I32, 0)
    29  	cond := f.cur.NewICmp(enum.IPredNE, ecx, zero)
    30  	return f.liftTermJcc(term.Arg(0), cond)
    31  }
    32  
    33  // --- [ LOOPE ] ---------------------------------------------------------------
    34  
    35  // liftTermLOOPE lifts the given x86 LOOPE instruction to LLVM IR, emitting code
    36  // to f.
    37  func (f *Func) liftTermLOOPE(term *x86.Inst) error {
    38  	// Loop if equal and ECX register is not zero.
    39  	//    (ECX≠0 and ZF=1)
    40  	ecx := f.dec(x86.NewArg(x86asm.ECX, term))
    41  	zero := constant.NewInt(types.I32, 0)
    42  	zf := f.useStatus(ZF)
    43  	cond1 := f.cur.NewICmp(enum.IPredNE, ecx, zero)
    44  	cond2 := zf
    45  	cond := f.cur.NewAnd(cond1, cond2)
    46  	return f.liftTermJcc(term.Arg(0), cond)
    47  }
    48  
    49  // --- [ LOOPNE ] --------------------------------------------------------------
    50  
    51  // liftTermLOOPNE lifts the given x86 LOOPNE instruction to LLVM IR, emitting
    52  // code to f.
    53  func (f *Func) liftTermLOOPNE(term *x86.Inst) error {
    54  	// Loop if not equal and ECX register is not zero.
    55  	//    (ECX≠0 and ZF=0)
    56  	ecx := f.dec(x86.NewArg(x86asm.ECX, term))
    57  	zero := constant.NewInt(types.I32, 0)
    58  	zf := f.useStatus(ZF)
    59  	cond1 := f.cur.NewICmp(enum.IPredNE, ecx, zero)
    60  	cond2 := f.cur.NewICmp(enum.IPredEQ, zf, constant.False)
    61  	cond := f.cur.NewAnd(cond1, cond2)
    62  	return f.liftTermJcc(term.Arg(0), cond)
    63  }