From 9da46e3992429b1d8aff1d725abbf81759e1c5f8 Mon Sep 17 00:00:00 2001 From: Ajax Date: Thu, 12 Nov 2015 12:23:15 +0100 Subject: x86/sem: refactor sar / shr using a common template --- miasm2/arch/x86/sem.py | 48 ++++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index b622e930..30f1daee 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -468,23 +468,28 @@ def rcr(ir, instr, a, b): return e, [] -def sar(ir, instr, a, b): +def _shift_tpl(op, ir, instr, a, b, c=None): + """Template for generate shifter with operation `op` + A temporary basic block is generated to handle 0-shift + @op: operation to execute + @c (optional): if set, instruction has a bit provider + """ shifter = get_shift(a, b) - c = m2_expr.ExprOp('a>>', a, shifter) + res = m2_expr.ExprOp(op, a, shifter) lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode) lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) - new_cf = m2_expr.ExprOp('a>>', a,(shifter - m2_expr.ExprInt_from(a, 1)))[:1] + new_cf = m2_expr.ExprOp(op, a,(shifter - m2_expr.ExprInt_from(a, 1)))[:1] e_do = [ m2_expr.ExprAff(cf, new_cf), m2_expr.ExprAff(of, m2_expr.ExprInt_from(of, 0)), - m2_expr.ExprAff(a, c), + m2_expr.ExprAff(a, res), ] - e_do += update_flag_znp(c) + e_do += update_flag_znp(res) # dont generate conditional shifter on constant if isinstance(shifter, m2_expr.ExprInt): @@ -501,37 +506,12 @@ def sar(ir, instr, a, b): return e, [irbloc(lbl_do.name, [e_do])] -def shr(ir, instr, a, b): - - shifter = get_shift(a, b) - c = m2_expr.ExprOp('>>', a, shifter) - - lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode) - lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) - - new_cf = m2_expr.ExprOp('>>', a, (shifter - m2_expr.ExprInt_from(a, 1)))[:1] - - e_do = [ - m2_expr.ExprAff(cf, new_cf), - m2_expr.ExprAff(of, m2_expr.ExprInt_from(of, 0)), - m2_expr.ExprAff(a, c), - ] - - e_do += update_flag_znp(c) - - # dont generate conditional shifter on constant - if isinstance(shifter, m2_expr.ExprInt): - if int(shifter.arg) != 0: - return e_do, [] - else: - return [], [] +def sar(ir, instr, a, b): + return _shift_tpl("a>>", ir, instr, a, b) - e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) - e = [] - e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(shifter, lbl_do, - lbl_skip))) - return e, [irbloc(lbl_do.name, [e_do])] +def shr(ir, instr, a, b): + return _shift_tpl(">>", ir, instr, a, b) def shrd_cl(ir, instr, a, b): -- cgit 1.4.1 From f0d72245c9a295958a972340c3e895596d682d8e Mon Sep 17 00:00:00 2001 From: Ajax Date: Thu, 12 Nov 2015 15:32:35 +0100 Subject: x86/sem: handle count == 0 in `shrd` --- miasm2/arch/x86/sem.py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 30f1daee..60fb0a81 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -468,15 +468,23 @@ def rcr(ir, instr, a, b): return e, [] -def _shift_tpl(op, ir, instr, a, b, c=None): - """Template for generate shifter with operation `op` +def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None): + """Template for generate shifter with operation @op A temporary basic block is generated to handle 0-shift @op: operation to execute @c (optional): if set, instruction has a bit provider + @op_inv (optional): opposite operation of @op. Must be provided if @c """ + if c is not None: + shifter = get_shift(a, c) + else: + shifter = get_shift(a, b) - shifter = get_shift(a, b) res = m2_expr.ExprOp(op, a, shifter) + if c is not None: + shifter_inv = m2_expr.ExprInt_from(a, a.size) - c.zeroExtend(a.size) + res |= m2_expr.ExprOp(op_inv, b, + shifter_inv) lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode) lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) @@ -533,20 +541,7 @@ def shrd_cl(ir, instr, a, b): def shrd(ir, instr, a, b, c): - e = [] - shifter = get_shift(a, c) - - d = (a >> shifter) | (b << (m2_expr.ExprInt_from(a, a.size) - shifter)) - new_cf = (a >> (shifter - m2_expr.ExprInt_from(a, 1)))[:1] - e.append(m2_expr.ExprAff(cf, m2_expr.ExprCond(shifter, - new_cf, - cf) - ) - ) - e.append(m2_expr.ExprAff(of, a.msb())) - e += update_flag_znp(d) - e.append(m2_expr.ExprAff(a, d)) - return e, [] + return _shift_tpl(">>", ir, instr, a, b, c, "<<") def sal(ir, instr, a, b): -- cgit 1.4.1 From f761f21ad0862e00a160155e37c0eea711b3d4ce Mon Sep 17 00:00:00 2001 From: Ajax Date: Thu, 12 Nov 2015 18:46:01 +0100 Subject: x86/sem: emulate overflow 'undefined behavior' for shrd --- miasm2/arch/x86/sem.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 60fb0a81..96f0bb62 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -481,16 +481,35 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None): shifter = get_shift(a, b) res = m2_expr.ExprOp(op, a, shifter) + cf_from_dst = m2_expr.ExprOp(op, a, + (shifter - m2_expr.ExprInt_from(a, 1)))[:1] if c is not None: - shifter_inv = m2_expr.ExprInt_from(a, a.size) - c.zeroExtend(a.size) - res |= m2_expr.ExprOp(op_inv, b, - shifter_inv) + # There is a source for new bits + i1 = m2_expr.ExprInt(1, size=a.size) + isize = m2_expr.ExprInt(a.size, size=a.size) + mask = m2_expr.ExprOp(op_inv, i1, (isize - shifter)) - i1 + + # An overflow can occured, emulate the 'undefined behavior' + # Overflow behavior if (shift / size % 2) + cond_overflow = ((c - m2_expr.ExprInt(1, size=c.size)) & + m2_expr.ExprInt(a.size, c.size)) + mask = m2_expr.ExprCond(cond_overflow, ~mask, mask) + + # Build res with dst and src + res = ((m2_expr.ExprOp(op, a, shifter) & mask) | + (m2_expr.ExprOp(op_inv, b, (isize - shifter)) & ~mask)) + + # Overflow case: cf come from src (bit number shifter % size) + cf_from_src = m2_expr.ExprOp(op, b, + (c.zeroExtend(b.size) & m2_expr.ExprInt(a.size - 1, b.size)) - i1)[:1] + new_cf = m2_expr.ExprCond(cond_overflow, cf_from_src, cf_from_dst) + + else: + new_cf = cf_from_dst lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode) lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) - new_cf = m2_expr.ExprOp(op, a,(shifter - m2_expr.ExprInt_from(a, 1)))[:1] - e_do = [ m2_expr.ExprAff(cf, new_cf), m2_expr.ExprAff(of, m2_expr.ExprInt_from(of, 0)), @@ -541,7 +560,7 @@ def shrd_cl(ir, instr, a, b): def shrd(ir, instr, a, b, c): - return _shift_tpl(">>", ir, instr, a, b, c, "<<") + return _shift_tpl(">>>", ir, instr, a, b, c, "<<<") def sal(ir, instr, a, b): -- cgit 1.4.1 From ab17bd233f0000e8e95295742db7d1e8cf8a722c Mon Sep 17 00:00:00 2001 From: Ajax Date: Thu, 12 Nov 2015 18:54:13 +0100 Subject: x86/sem: handle overflow flag in shrd --- miasm2/arch/x86/sem.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 96f0bb62..9763b07c 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -512,7 +512,9 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None): e_do = [ m2_expr.ExprAff(cf, new_cf), - m2_expr.ExprAff(of, m2_expr.ExprInt_from(of, 0)), + m2_expr.ExprAff(of, m2_expr.ExprCond(shifter - m2_expr.ExprInt(1, size=shifter.size), + m2_expr.ExprInt_from(of, 0), + b[:1] ^ a.msb())), m2_expr.ExprAff(a, res), ] -- cgit 1.4.1 From f62aba88c71fc3c62ac4890e0237553c30a208e7 Mon Sep 17 00:00:00 2001 From: Ajax Date: Thu, 12 Nov 2015 19:04:23 +0100 Subject: x86/sem: use shift_tpl for shld A refactor is needed, some comments are missing --- miasm2/arch/x86/sem.py | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 9763b07c..aeb62531 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -468,7 +468,7 @@ def rcr(ir, instr, a, b): return e, [] -def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None): +def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): """Template for generate shifter with operation @op A temporary basic block is generated to handle 0-shift @op: operation to execute @@ -493,6 +493,8 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None): # Overflow behavior if (shift / size % 2) cond_overflow = ((c - m2_expr.ExprInt(1, size=c.size)) & m2_expr.ExprInt(a.size, c.size)) + if left: + mask = ~mask mask = m2_expr.ExprCond(cond_overflow, ~mask, mask) # Build res with dst and src @@ -602,26 +604,7 @@ def shld_cl(ir, instr, a, b): def shld(ir, instr, a, b, c): - e = [] - shifter = c.zeroExtend(a.size) & m2_expr.ExprInt_from(a, 0x1f) - c = m2_expr.ExprOp('|', - a << shifter, - b >> (m2_expr.ExprInt_from(a, a.size) - shifter) - ) - - new_cf = (a >> (m2_expr.ExprInt_from(a, a.size) - shifter))[:1] - e.append(m2_expr.ExprAff(cf, m2_expr.ExprCond(shifter, - new_cf, - cf) - ) - ) - # XXX todo: don't update flag if shifter is 0 - e += update_flag_znp(c) - e.append(m2_expr.ExprAff(of, c.msb() ^ new_cf)) - e.append(m2_expr.ExprAff(a, m2_expr.ExprCond(shifter, - c, - a))) - return e, [] + return _shift_tpl("<<<", ir, instr, a, b, c, ">>>", left=True) # XXX todo ### -- cgit 1.4.1 From 2982c0635d94545c25072f28de915c1334312039 Mon Sep 17 00:00:00 2001 From: Ajax Date: Thu, 12 Nov 2015 19:04:49 +0100 Subject: x86/sem: fix overflow flag for shld --- miasm2/arch/x86/sem.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index aeb62531..308090e4 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -483,9 +483,9 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): res = m2_expr.ExprOp(op, a, shifter) cf_from_dst = m2_expr.ExprOp(op, a, (shifter - m2_expr.ExprInt_from(a, 1)))[:1] + i1 = m2_expr.ExprInt(1, size=a.size) if c is not None: # There is a source for new bits - i1 = m2_expr.ExprInt(1, size=a.size) isize = m2_expr.ExprInt(a.size, size=a.size) mask = m2_expr.ExprOp(op_inv, i1, (isize - shifter)) - i1 @@ -512,11 +512,12 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode) lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) + value_of = a.msb() ^ a[-2:-1] if left else b[:1] ^ a.msb() e_do = [ m2_expr.ExprAff(cf, new_cf), - m2_expr.ExprAff(of, m2_expr.ExprCond(shifter - m2_expr.ExprInt(1, size=shifter.size), + m2_expr.ExprAff(of, m2_expr.ExprCond(shifter - i1, m2_expr.ExprInt_from(of, 0), - b[:1] ^ a.msb())), + value_of)), m2_expr.ExprAff(a, res), ] -- cgit 1.4.1 From 18bcd354ee95348227d97bca9fbd5acfb9476d56 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 10:33:50 +0100 Subject: x86/sem: fix shld for 'undefined behavior' --- miasm2/arch/x86/sem.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 308090e4..5d2df31f 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -482,7 +482,12 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): res = m2_expr.ExprOp(op, a, shifter) cf_from_dst = m2_expr.ExprOp(op, a, - (shifter - m2_expr.ExprInt_from(a, 1)))[:1] + (shifter - m2_expr.ExprInt_from(a, 1))) + if left: + cf_from_dst = cf_from_dst.msb() + else: + cf_from_dst = cf_from_dst[:1] + i1 = m2_expr.ExprInt(1, size=a.size) if c is not None: # There is a source for new bits @@ -491,11 +496,12 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): # An overflow can occured, emulate the 'undefined behavior' # Overflow behavior if (shift / size % 2) - cond_overflow = ((c - m2_expr.ExprInt(1, size=c.size)) & - m2_expr.ExprInt(a.size, c.size)) + base_cond_overflow = c if left else (c - m2_expr.ExprInt(1, size=c.size)) + cond_overflow = base_cond_overflow & m2_expr.ExprInt(a.size, c.size) if left: - mask = ~mask - mask = m2_expr.ExprCond(cond_overflow, ~mask, mask) + mask = m2_expr.ExprCond(cond_overflow, mask, ~mask) + else: + mask = m2_expr.ExprCond(cond_overflow, ~mask, mask) # Build res with dst and src res = ((m2_expr.ExprOp(op, a, shifter) & mask) | @@ -503,7 +509,11 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): # Overflow case: cf come from src (bit number shifter % size) cf_from_src = m2_expr.ExprOp(op, b, - (c.zeroExtend(b.size) & m2_expr.ExprInt(a.size - 1, b.size)) - i1)[:1] + (c.zeroExtend(b.size) & m2_expr.ExprInt(a.size - 1, b.size)) - i1) + if left: + cf_from_src = cf_from_src.msb() + else: + cf_from_src = cf_from_src[:1] new_cf = m2_expr.ExprCond(cond_overflow, cf_from_src, cf_from_dst) else: -- cgit 1.4.1 From 0c86e96949f6b478d63a5e5d02ecde833dd701e4 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 10:43:00 +0100 Subject: x86/sem: refactor _shift_tpl --- miasm2/arch/x86/sem.py | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 5d2df31f..597f19df 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -474,6 +474,7 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): @op: operation to execute @c (optional): if set, instruction has a bit provider @op_inv (optional): opposite operation of @op. Must be provided if @c + @left (optional): indicates a left shift if set, default is False """ if c is not None: shifter = get_shift(a, c) @@ -483,11 +484,9 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): res = m2_expr.ExprOp(op, a, shifter) cf_from_dst = m2_expr.ExprOp(op, a, (shifter - m2_expr.ExprInt_from(a, 1))) - if left: - cf_from_dst = cf_from_dst.msb() - else: - cf_from_dst = cf_from_dst[:1] + cf_from_dst = cf_from_dst.msb() if left else cf_from_dst[:1] + new_cf = cf_from_dst i1 = m2_expr.ExprInt(1, size=a.size) if c is not None: # There is a source for new bits @@ -499,6 +498,7 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): base_cond_overflow = c if left else (c - m2_expr.ExprInt(1, size=c.size)) cond_overflow = base_cond_overflow & m2_expr.ExprInt(a.size, c.size) if left: + # Overflow occurs one round before right mask = m2_expr.ExprCond(cond_overflow, mask, ~mask) else: mask = m2_expr.ExprCond(cond_overflow, ~mask, mask) @@ -509,20 +509,15 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): # Overflow case: cf come from src (bit number shifter % size) cf_from_src = m2_expr.ExprOp(op, b, - (c.zeroExtend(b.size) & m2_expr.ExprInt(a.size - 1, b.size)) - i1) - if left: - cf_from_src = cf_from_src.msb() - else: - cf_from_src = cf_from_src[:1] + (c.zeroExtend(b.size) & + m2_expr.ExprInt(a.size - 1, b.size)) - i1) + cf_from_src = cf_from_src.msb() if left else cf_from_src[:1] new_cf = m2_expr.ExprCond(cond_overflow, cf_from_src, cf_from_dst) - else: - new_cf = cf_from_dst - - lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode) - lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) - + # Overflow flag, only occured when shifter is equal to 1 value_of = a.msb() ^ a[-2:-1] if left else b[:1] ^ a.msb() + + # Build basic blocks e_do = [ m2_expr.ExprAff(cf, new_cf), m2_expr.ExprAff(of, m2_expr.ExprCond(shifter - i1, @@ -530,19 +525,19 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): value_of)), m2_expr.ExprAff(a, res), ] - e_do += update_flag_znp(res) - # dont generate conditional shifter on constant + # Don't generate conditional shifter on constant if isinstance(shifter, m2_expr.ExprInt): if int(shifter.arg) != 0: return e_do, [] else: return [], [] - e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) - e = [] + lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode) + lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) + e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(shifter, lbl_do, lbl_skip))) return e, [irbloc(lbl_do.name, [e_do])] -- cgit 1.4.1 From c45e68462a1f7ab6822a7f723b3aa00c0f14afd6 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 11:04:32 +0100 Subject: x86/sem: introduce a template for rotate, handling 0-rotate RCL has been rewritte to use it --- miasm2/arch/x86/sem.py | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 597f19df..9b961de8 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -415,6 +415,42 @@ def get_shift(a, b): shift = expr_simp(shift) return shift +def _rotate_tpl(ir, instr, a, b, op, op_cf=None): + """Template for generate rotater with operation @op + A temporary basic block is generated to handle 0-rotate + @op: operation to execute + @op_cf (optional): operation to use for carry flag. If not set, use @op + """ + if op_cf is None: + op_cf = op + + shifter = get_shift(a, b) + res = m2_expr.ExprOp(op, a, shifter, cf.zeroExtend(a.size)) + new_cf = m2_expr.ExprOp(op_cf, a, shifter, cf.zeroExtend(a.size))[:1] + + # Build basic blocks + e_do = [ + m2_expr.ExprAff(cf, new_cf), + # hack (only valid if b=1) + m2_expr.ExprAff(of, res.msb() ^ new_cf), + m2_expr.ExprAff(a, res), + ] + + # Don't generate conditional shifter on constant + if isinstance(shifter, m2_expr.ExprInt): + if int(shifter.arg) != 0: + return e_do, [] + else: + return [], [] + + e = [] + lbl_do = m2_expr.ExprId(ir.gen_label(), instr.mode) + lbl_skip = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) + e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) + e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(shifter, lbl_do, + lbl_skip))) + return e, [irbloc(lbl_do.name, [e_do])] + def l_rol(ir, instr, a, b): e = [] @@ -442,16 +478,7 @@ def l_ror(ir, instr, a, b): def rcl(ir, instr, a, b): - e = [] - shifter = get_shift(a, b) - c = m2_expr.ExprOp('<< Date: Fri, 13 Nov 2015 11:29:21 +0100 Subject: x86/sem: use _rotate_tpl for RCR --- miasm2/arch/x86/sem.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 9b961de8..d0a18897 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -415,11 +415,12 @@ def get_shift(a, b): shift = expr_simp(shift) return shift -def _rotate_tpl(ir, instr, a, b, op, op_cf=None): +def _rotate_tpl(ir, instr, a, b, op, op_cf=None, left=False): """Template for generate rotater with operation @op A temporary basic block is generated to handle 0-rotate @op: operation to execute @op_cf (optional): operation to use for carry flag. If not set, use @op + @left (optional): indicates a left rotate if set, default is False """ if op_cf is None: op_cf = op @@ -478,21 +479,11 @@ def l_ror(ir, instr, a, b): def rcl(ir, instr, a, b): - return _rotate_tpl(ir, instr, a, b, '<<>>c_rez', a, shifter, cf.zeroExtend(a.size)) - new_cf = m2_expr.ExprOp('>>>c_cf', a, shifter, cf.zeroExtend(a.size))[:1] - - e.append(m2_expr.ExprAff(cf, new_cf)) - # hack (only valid if b=1) - e.append(m2_expr.ExprAff(of, (a ^ c).msb())) - e.append(m2_expr.ExprAff(a, c)) - - return e, [] + return _rotate_tpl(ir, instr, a, b, '>>>c_rez', '>>>c_cf') def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): -- cgit 1.4.1 From e4627f5c4ea3e0f3e3555d7d72d7be0cfeefbf6e Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 11:29:38 +0100 Subject: x86/sem: fix overflow flag condition in rotation --- miasm2/arch/x86/sem.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index d0a18897..d8648644 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -429,11 +429,13 @@ def _rotate_tpl(ir, instr, a, b, op, op_cf=None, left=False): res = m2_expr.ExprOp(op, a, shifter, cf.zeroExtend(a.size)) new_cf = m2_expr.ExprOp(op_cf, a, shifter, cf.zeroExtend(a.size))[:1] + new_of = m2_expr.ExprCond(b - m2_expr.ExprInt(1, size=b.size), + m2_expr.ExprInt(0, size=of.size), + res.msb() ^ new_cf if left else (a ^ res).msb()) # Build basic blocks e_do = [ m2_expr.ExprAff(cf, new_cf), - # hack (only valid if b=1) - m2_expr.ExprAff(of, res.msb() ^ new_cf), + m2_expr.ExprAff(of, new_of), m2_expr.ExprAff(a, res), ] -- cgit 1.4.1 From d6a6f4aaa661ee45232b9b985f7b59c516b8b6c4 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 11:54:46 +0100 Subject: x86: >>>/<<< c_cf are no more needed: use c_rez with rotate-1 --- miasm2/arch/x86/sem.py | 15 +++++++-------- miasm2/ir/translators/C.py | 2 -- miasm2/jitter/vm_mngr.c | 35 ++--------------------------------- miasm2/jitter/vm_mngr.h | 3 +-- 4 files changed, 10 insertions(+), 45 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index d8648644..f77fc2d4 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -415,20 +415,19 @@ def get_shift(a, b): shift = expr_simp(shift) return shift -def _rotate_tpl(ir, instr, a, b, op, op_cf=None, left=False): +def _rotate_tpl(ir, instr, a, b, op, left=False): """Template for generate rotater with operation @op A temporary basic block is generated to handle 0-rotate @op: operation to execute - @op_cf (optional): operation to use for carry flag. If not set, use @op @left (optional): indicates a left rotate if set, default is False """ - if op_cf is None: - op_cf = op - shifter = get_shift(a, b) res = m2_expr.ExprOp(op, a, shifter, cf.zeroExtend(a.size)) - new_cf = m2_expr.ExprOp(op_cf, a, shifter, cf.zeroExtend(a.size))[:1] + new_cf = m2_expr.ExprOp(op, a, + shifter - m2_expr.ExprInt(1, size=shifter.size), + cf.zeroExtend(a.size)) + new_cf = new_cf.msb() if left else new_cf[:1] new_of = m2_expr.ExprCond(b - m2_expr.ExprInt(1, size=b.size), m2_expr.ExprInt(0, size=of.size), res.msb() ^ new_cf if left else (a ^ res).msb()) @@ -481,11 +480,11 @@ def l_ror(ir, instr, a, b): def rcl(ir, instr, a, b): - return _rotate_tpl(ir, instr, a, b, '<<>>c_rez', '>>>c_cf') + return _rotate_tpl(ir, instr, a, b, '>>>c_rez') def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py index e9d799ca..72759900 100644 --- a/miasm2/ir/translators/C.py +++ b/miasm2/ir/translators/C.py @@ -23,9 +23,7 @@ class TranslatorC(Translator): 'div32': "div_op", 'idiv32': "div_op", # XXX to test '<<>>c_rez': 'rcr_rez_op', - '>>>c_cf': 'rcr_cf_op', } diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c index 9ba3c227..ddcf86ca 100644 --- a/miasm2/jitter/vm_mngr.c +++ b/miasm2/jitter/vm_mngr.c @@ -847,7 +847,7 @@ uint64_t rot_right(uint64_t size, uint64_t a, uint64_t b) } -int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) +unsigned int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) { uint64_t tmp; @@ -887,43 +887,12 @@ int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c } } -int rcr_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) +unsigned int rcr_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) { return rcl_rez_op(size, a, size+1-b, cf); } - -int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) -{ - uint64_t tmp; - - tmp = (cf<< size) | a; - - size++; - b %= size; - - switch(size){ - case 8+1: - tmp = (tmp << b) | ((tmp&0x1FF) >> (size-b)); - return (tmp>>8)&1; - case 16+1: - tmp = (tmp << b) | ((tmp&0x1FFFF) >> (size-b)); - return (tmp>>16)&1; - case 32+1: - tmp = (tmp << b) | ((tmp&0x1FFFFFFFFULL) >> (size-b)); - return (tmp>>32)&1; - default: - fprintf(stderr, "inv size in rclleft %d\n", size); - exit(0); - } -} - -int rcr_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) -{ - return rcl_cf_op(size, a, size+1-b, cf); -} - unsigned int x86_bsr(uint64_t src, unsigned int size) { int i; diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h index 8653dd55..f5895e12 100644 --- a/miasm2/jitter/vm_mngr.h +++ b/miasm2/jitter/vm_mngr.h @@ -206,8 +206,7 @@ unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c); uint64_t rot_left(uint64_t size, uint64_t a, uint64_t b); uint64_t rot_right(uint64_t size, uint64_t a, uint64_t b); -int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf); -int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf); +unsigned int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf); #define UDIV(sizeA) \ -- cgit 1.4.1 From aacbb36ce44c91ccb51137df8e8f8f841dac2d36 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 14:08:03 +0100 Subject: x86/sem: fix ror semantics (handle 0-round case) --- miasm2/arch/x86/sem.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index f77fc2d4..d8f1726c 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -415,19 +415,25 @@ def get_shift(a, b): shift = expr_simp(shift) return shift -def _rotate_tpl(ir, instr, a, b, op, left=False): +def _rotate_tpl(ir, instr, a, b, op, left=False, include_cf=False): """Template for generate rotater with operation @op A temporary basic block is generated to handle 0-rotate @op: operation to execute @left (optional): indicates a left rotate if set, default is False + @include_cf (optional): if set, add cf to @op inputs, default is False """ + # Compute results shifter = get_shift(a, b) - res = m2_expr.ExprOp(op, a, shifter, cf.zeroExtend(a.size)) + extended_args = (cf.zeroExtend(a.size),) if include_cf else () + res = m2_expr.ExprOp(op, a, shifter, *extended_args) + # CF is computed with 1-less round than `res` new_cf = m2_expr.ExprOp(op, a, shifter - m2_expr.ExprInt(1, size=shifter.size), - cf.zeroExtend(a.size)) + *extended_args) new_cf = new_cf.msb() if left else new_cf[:1] + + # OF is defined only for @b == 1 new_of = m2_expr.ExprCond(b - m2_expr.ExprInt(1, size=b.size), m2_expr.ExprInt(0, size=of.size), res.msb() ^ new_cf if left else (a ^ res).msb()) @@ -468,23 +474,15 @@ def l_rol(ir, instr, a, b): def l_ror(ir, instr, a, b): - e = [] - shifter = get_shift(a, b) - c = m2_expr.ExprOp('>>>', a, shifter) - - e.append(m2_expr.ExprAff(cf, c.msb())) - # hack (only valid if b=1): when count == 1: a = msb-1(dest) - e.append(m2_expr.ExprAff(of, (c ^ a).msb())) - e.append(m2_expr.ExprAff(a, c)) - return e, [] + return _rotate_tpl(ir, instr, a, b, '>>>') def rcl(ir, instr, a, b): - return _rotate_tpl(ir, instr, a, b, '<<>>c_rez') + return _rotate_tpl(ir, instr, a, b, '>>>c_rez', include_cf=True) def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): -- cgit 1.4.1 From 23523f31b741ed1a901cdb56e862ab7ed9bc9474 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 14:09:31 +0100 Subject: x86/sem: fix rol semantics (handle 0-round case) --- miasm2/arch/x86/sem.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index d8f1726c..dc7841b9 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -461,16 +461,7 @@ def _rotate_tpl(ir, instr, a, b, op, left=False, include_cf=False): def l_rol(ir, instr, a, b): - e = [] - shifter = get_shift(a, b) - c = m2_expr.ExprOp('<<<', a, shifter) - - new_cf = c[:1] - e.append(m2_expr.ExprAff(cf, new_cf)) - # hack (only valid if b=1) - e.append(m2_expr.ExprAff(of, c.msb() ^ new_cf)) - e.append(m2_expr.ExprAff(a, c)) - return e, [] + return _rotate_tpl(ir, instr, a, b, '<<<', left=True) def l_ror(ir, instr, a, b): -- cgit 1.4.1 From 5d66a91c9aa4d3a0291854ea4bad12fe520b4806 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 14:22:34 +0100 Subject: x86/sem: fix OF calculation for sar --- miasm2/arch/x86/sem.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index dc7841b9..295d05c2 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -476,13 +476,15 @@ def rcr(ir, instr, a, b): return _rotate_tpl(ir, instr, a, b, '>>>c_rez', include_cf=True) -def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): +def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, + custom_of=None): """Template for generate shifter with operation @op A temporary basic block is generated to handle 0-shift @op: operation to execute @c (optional): if set, instruction has a bit provider @op_inv (optional): opposite operation of @op. Must be provided if @c @left (optional): indicates a left shift if set, default is False + @custom_of (optional): if set, override the computed value of OF """ if c is not None: shifter = get_shift(a, c) @@ -523,7 +525,10 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): new_cf = m2_expr.ExprCond(cond_overflow, cf_from_src, cf_from_dst) # Overflow flag, only occured when shifter is equal to 1 - value_of = a.msb() ^ a[-2:-1] if left else b[:1] ^ a.msb() + if custom_of is None: + value_of = a.msb() ^ a[-2:-1] if left else b[:1] ^ a.msb() + else: + value_of = custom_of # Build basic blocks e_do = [ @@ -552,7 +557,9 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False): def sar(ir, instr, a, b): - return _shift_tpl("a>>", ir, instr, a, b) + # Fixup OF, always cleared if b != 0 + i0 = m2_expr.ExprInt(0, size=of.size) + return _shift_tpl("a>>", ir, instr, a, b, custom_of=i0) def shr(ir, instr, a, b): -- cgit 1.4.1 From 9f5e46bffb5db36e79451f61a1b73a0bb4fc25ed Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 14:24:54 +0100 Subject: x86/sem: fix OF calculation for shr --- miasm2/arch/x86/sem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 295d05c2..5bf4a7a1 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -563,7 +563,7 @@ def sar(ir, instr, a, b): def shr(ir, instr, a, b): - return _shift_tpl(">>", ir, instr, a, b) + return _shift_tpl(">>", ir, instr, a, b, custom_of=a.msb()) def shrd_cl(ir, instr, a, b): -- cgit 1.4.1 From dfe2e8bc8fd761c5c05623564742c18daafaf48d Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 14:25:22 +0100 Subject: x86/sem: fix SHL (handle 0-round case) --- miasm2/arch/x86/sem.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 5bf4a7a1..521062c5 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -605,19 +605,7 @@ def sal(ir, instr, a, b): def shl(ir, instr, a, b): - e = [] - shifter = get_shift(a, b) - c = a << shifter - new_cf = (a >> (m2_expr.ExprInt_from(a, a.size) - shifter))[:1] - e.append(m2_expr.ExprAff(cf, m2_expr.ExprCond(shifter, - new_cf, - cf) - ) - ) - e += update_flag_znp(c) - e.append(m2_expr.ExprAff(of, c.msb() ^ new_cf)) - e.append(m2_expr.ExprAff(a, c)) - return e, [] + return _shift_tpl("<<", ir, instr, a, b, left=True) def shld_cl(ir, instr, a, b): -- cgit 1.4.1 From 82dfd90cb3f25b60329805c8d2e19216e1159514 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 16:02:00 +0100 Subject: x86/sem: correct AFLAG (special case for dec) --- miasm2/arch/x86/sem.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 521062c5..b2097e58 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -73,8 +73,8 @@ def update_flag_pf(a): a & m2_expr.ExprInt_from(a, 0xFF)))] -def update_flag_af(expr): - return [m2_expr.ExprAff(af, expr[4:5])] +def update_flag_af(op1, op2, res): + return [m2_expr.ExprAff(af, (op1 ^ op2 ^ res)[4:5])] def update_flag_znp(a): @@ -286,7 +286,7 @@ def add(ir, instr, a, b): e = [] c = a + b e += update_flag_arith(c) - e += update_flag_af(c) + e += update_flag_af(a, b, c) e += update_flag_add(a, b, c) e.append(m2_expr.ExprAff(a, c)) return e, [] @@ -296,7 +296,7 @@ def xadd(ir, instr, a, b): e = [] c = a + b e += update_flag_arith(c) - e += update_flag_af(c) + e += update_flag_af(a, b, c) e += update_flag_add(b, a, c) e.append(m2_expr.ExprAff(b, a)) e.append(m2_expr.ExprAff(a, c)) @@ -309,7 +309,7 @@ def adc(ir, instr, a, b): 1, a.size), (cf, 0, 1)])) e += update_flag_arith(c) - e += update_flag_af(c) + e += update_flag_af(a, b, c) e += update_flag_add(a, b, c) e.append(m2_expr.ExprAff(a, c)) return e, [] @@ -319,7 +319,7 @@ def sub(ir, instr, a, b): e = [] c = a - b e += update_flag_arith(c) - e += update_flag_af(c) + e += update_flag_af(a, b, c) e += update_flag_sub(a, b, c) e.append(m2_expr.ExprAff(a, c)) return e, [] @@ -333,7 +333,7 @@ def sbb(ir, instr, a, b): 1, a.size), (cf, 0, 1)])) e += update_flag_arith(c) - e += update_flag_af(c) + e += update_flag_af(a, b, c) e += update_flag_sub(a, b, c) e.append(m2_expr.ExprAff(a, c)) return e, [] @@ -346,7 +346,7 @@ def neg(ir, instr, b): c = a - b e += update_flag_arith(c) e += update_flag_sub(a, b, c) - e += update_flag_af(c) + e += update_flag_af(a, b, c) e.append(m2_expr.ExprAff(b, c)) return e, [] @@ -363,7 +363,7 @@ def l_cmp(ir, instr, a, b): c = a - b e += update_flag_arith(c) e += update_flag_sub(a, b, c) - e += update_flag_af(c) + e += update_flag_af(a, b, c) return e, [] @@ -659,7 +659,7 @@ def inc(ir, instr, a): b = m2_expr.ExprInt_from(a, 1) c = a + b e += update_flag_arith(c) - e += update_flag_af(c) + e += update_flag_af(a, b, c) e.append(update_flag_add_of(a, b, c)) e.append(m2_expr.ExprAff(a, c)) @@ -670,7 +670,7 @@ def dec(ir, instr, a): b = m2_expr.ExprInt_from(a, -1) c = a + b e += update_flag_arith(c) - e += update_flag_af(c) + e += update_flag_af(a, b, ~c) e.append(update_flag_add_of(a, b, c)) e.append(m2_expr.ExprAff(a, c)) -- cgit 1.4.1 From 1fb09685622caeb20af42b09929857190a8d32a2 Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 16:24:50 +0100 Subject: x86/sem: LOOP* should use opmode instead of admode --- miasm2/arch/x86/sem.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index b2097e58..a5bdb46d 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -1345,8 +1345,7 @@ def jno(ir, instr, dst): def loop(ir, instr, dst): e = [] meip = mRIP[instr.mode] - s = instr.v_opmode() - opmode, admode = s, instr.v_admode() + admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) @@ -1363,13 +1362,12 @@ def loop(ir, instr, dst): def loopne(ir, instr, dst): e = [] meip = mRIP[instr.mode] - s = instr.v_opmode() - opmode, admode = s, instr.v_admode() + admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) - c = m2_expr.ExprCond(mRCX[instr.mode][:s] - m2_expr.ExprInt(1, s), + c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size), m2_expr.ExprInt1(1), m2_expr.ExprInt1(0)) c &= zf ^ m2_expr.ExprInt1(1) @@ -1386,12 +1384,11 @@ def loopne(ir, instr, dst): def loope(ir, instr, dst): e = [] meip = mRIP[instr.mode] - s = instr.v_opmode() - opmode, admode = s, instr.v_admode() + admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprId(ir.get_next_label(instr), instr.mode) - c = m2_expr.ExprCond(mRCX[instr.mode][:s] - m2_expr.ExprInt(1, s), + c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size), m2_expr.ExprInt1(1), m2_expr.ExprInt1(0)) c &= zf -- cgit 1.4.1 From 8ae102ba0fd8231c9d491a308144b0dd5424e0df Mon Sep 17 00:00:00 2001 From: Ajax Date: Fri, 13 Nov 2015 17:27:30 +0100 Subject: x86/sem: fix typo (creds @serpilliere) --- miasm2/arch/x86/sem.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'miasm2/arch/x86/sem.py') diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index a5bdb46d..0e83de8c 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -416,7 +416,7 @@ def get_shift(a, b): return shift def _rotate_tpl(ir, instr, a, b, op, left=False, include_cf=False): - """Template for generate rotater with operation @op + """Template to generate a rotater with operation @op A temporary basic block is generated to handle 0-rotate @op: operation to execute @left (optional): indicates a left rotate if set, default is False @@ -478,7 +478,7 @@ def rcr(ir, instr, a, b): def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, custom_of=None): - """Template for generate shifter with operation @op + """Template to generate a shifter with operation @op A temporary basic block is generated to handle 0-shift @op: operation to execute @c (optional): if set, instruction has a bit provider -- cgit 1.4.1