github.com/decomp/exp@v0.0.0-20210624183419-6d058f5e1da6/lift/x86/inst_rep.go (about) 1 package x86 2 3 import ( 4 "fmt" 5 6 "github.com/decomp/exp/disasm/x86" 7 "github.com/kr/pretty" 8 "github.com/llir/llvm/ir" 9 "github.com/llir/llvm/ir/constant" 10 "github.com/llir/llvm/ir/enum" 11 "github.com/llir/llvm/ir/types" 12 "github.com/pkg/errors" 13 "golang.org/x/arch/x86/x86asm" 14 ) 15 16 // Repeat Prefixes 17 // 18 // Repeat prefix Terminating condition 1 Terminating condition 2 19 // 20 // REP RCX or (E)CX = 0 None 21 // REPE RCX or (E)CX = 0 ZF = 0 22 // REPNE RCX or (E)CX = 0 ZF = 1 23 // 24 // ref: $ 4.2 REP/REPE/REPZ/REPNE/REPNZ - Repeat String Operation Prefix, Intel 25 // 64 and IA-32 Architectures Software Developer's Manual 26 27 // liftREPInst lifs the given REP prefixed x86 instruction to LLVM IR, emitting 28 // code to f. 29 func (f *Func) liftREPInst(inst *x86.Inst) error { 30 loop := &ir.Block{} 31 body := &ir.Block{} 32 exit := &ir.Block{} 33 f.Blocks = append(f.Blocks, loop) 34 f.Blocks = append(f.Blocks, body) 35 f.Blocks = append(f.Blocks, exit) 36 f.cur.NewBr(loop) 37 // Generate loop basic block. 38 f.cur = loop 39 ecx := f.useReg(x86.ECX) 40 zero := constant.NewInt(types.I32, 0) 41 cond := f.cur.NewICmp(enum.IPredNE, ecx, zero) 42 f.cur.NewCondBr(cond, body, exit) 43 // Generate body basic block. 44 f.cur = body 45 switch inst.Op { 46 case x86asm.MOVSB: 47 if err := f.liftInstMOVSB(inst); err != nil { 48 return errors.WithStack(err) 49 } 50 case x86asm.MOVSD: 51 if err := f.liftInstMOVSD(inst); err != nil { 52 return errors.WithStack(err) 53 } 54 case x86asm.STOSB: 55 if err := f.liftInstSTOSB(inst); err != nil { 56 return errors.WithStack(err) 57 } 58 case x86asm.STOSW: 59 if err := f.liftInstSTOSW(inst); err != nil { 60 return errors.WithStack(err) 61 } 62 case x86asm.STOSD: 63 if err := f.liftInstSTOSD(inst); err != nil { 64 return errors.WithStack(err) 65 } 66 default: 67 panic(fmt.Errorf("support for REP prefixed %v instruction not yet implemented", inst.Op)) 68 } 69 ecx = f.useReg(x86.ECX) 70 one := constant.NewInt(types.I32, 1) 71 tmp := f.cur.NewSub(ecx, one) 72 f.defReg(x86.ECX, tmp) 73 f.cur.NewBr(loop) 74 // Generate exit block. 75 f.cur = exit 76 return nil 77 } 78 79 // liftREPNInst lifts the given REPN prefixed x86 instruction to LLVM IR, 80 // emitting code to f. 81 func (f *Func) liftREPNInst(inst *x86.Inst) error { 82 pretty.Println("inst:", inst) 83 panic("emitREPNInst: not yet implemented") 84 }