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 }