github/workflows/pycopy-test: Upgrade Pycopy to 3.6.1.
[ScratchABlock.git] / xform_inst.py
blobf0c801e35e106bfda1ed75aed5c52657f719c5b9
1 # ScratchABlock - Program analysis and decompilation framework
3 # Copyright (c) 2015-2018 Paul Sokolovsky
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 """Transformation passes on instructions"""
20 from xform_expr import *
21 import arch
24 def normalize_cond(inst):
25 "Normalize conditions so constants are on the right side."
26 if inst.op == "if":
27 inst.args[0].normalize()
30 def booleanize_cond(inst):
31 "Make conditions be of bool type (have bool operation)."
32 if inst.op == "if":
33 cond = inst.args[0]
34 if not cond.is_relation():
35 e = cond.expr
36 if is_expr(e) and e.op == "!":
37 new = EXPR("==", e.args[0], VALUE(0, 0))
38 else:
39 new = EXPR("!=", e, VALUE(0, 0))
40 cond.expr = new
43 def sub_const_to_add(inst):
44 "Replace subtractions of constant with adds."
46 inst.dest = expr_xform(inst.dest, expr_sub_const_to_add)
47 for i, a in enumerate(inst.args):
48 inst.args[i] = expr_xform(a, expr_sub_const_to_add)
51 def simplify_inst(inst):
52 if not (inst.dest and inst.op == "="):
53 return
54 assert len(inst.args) == 1
55 inst.args[0] = simplify_expr(inst.args[0])
58 def struct_access_inst(inst):
59 if not (inst.dest and inst.op == "="):
60 return
61 assert len(inst.args) == 1
62 inst.args[0] = struct_access_expr(inst.args[0])
65 def rewrite_complex_dest(inst):
66 "Rewrite casts and bitfield() on the left hand side of assignment."
68 dest = inst.dest
69 if not (inst.dest and inst.op == "="):
70 return
71 if not is_expr(inst.dest):
72 return
73 if dest.op == "CAST":
74 lsb = 0
75 size = dest.args[0].bitsize()
76 elif dest.op == "SFUNC" and dest.args[0].name == "bitfield":
77 assert is_value(dest.args[2]) and is_value(dest.args[3])
78 lsb = dest.args[2].val
79 size = dest.args[3].val
80 else:
81 assert 0
83 inst.dest = dest.args[1]
84 if lsb == 0 and size == arch.BITNESS:
85 return
87 all_ones = (1 << arch.BITNESS) - 1
88 mask = (1 << size) - 1
89 mask <<= lsb
90 if lsb == 0:
91 new_rhs = EXPR("&", inst.args[0], VALUE(mask))
92 else:
93 new_rhs = EXPR("&",
94 EXPR("<<", inst.args[0], VALUE(lsb, 10)),
95 VALUE(mask))
97 inst.args[0] = EXPR("|",
98 EXPR("&", inst.dest, VALUE(all_ones ^ mask)),
99 new_rhs)
102 def rewrite_stack_vars(inst, rewrite_to=CVAR):
103 "Rewrite memory references relative to sp0 to local variables."
104 def mem2loc(m):
105 if is_mem(m) and is_expr(m.expr) and set(m.expr.regs()) == {REG("sp_0")}:
106 name = "loc" + str(m.expr.args[1].val).replace("-", "_") + "_" + str(m.type)
107 return rewrite_to(name)
109 if inst.dest:
110 inst.dest = expr_xform(inst.dest, mem2loc)
112 for arg_no, arg in enumerate(inst.args):
113 inst.args[arg_no] = expr_xform(arg, mem2loc)