Skip to content

Commit 1d08371

Browse files
committed
ARM:LDRH: conversion for c expressions
1 parent 5eee4c7 commit 1d08371

File tree

1 file changed

+115
-38
lines changed

1 file changed

+115
-38
lines changed

chb/arm/opcodes/ARMLoadRegisterHalfword.py

Lines changed: 115 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@
5252

5353

5454
class ARMLoadRegisterHalfwordXData(ARMOpcodeXData):
55+
"""Data format:
56+
- variables:
57+
0: vrt (lhs)
58+
59+
- expressions:
60+
0: xrn
61+
1: xrm
62+
2: xmem (rhs)
63+
3: xrmem (rhs, rewritten)
64+
4: xaddr (address of rhs)
65+
66+
- c expressions:
67+
0: cxrmem (rhs)
68+
1: cxaddr (address of rhs)
69+
"""
5570

5671
def __init__(self, xdata: InstrXData) -> None:
5772
ARMOpcodeXData.__init__(self, xdata)
@@ -61,36 +76,79 @@ def vrt(self) -> "XVariable":
6176
return self.var(0, "vrt")
6277

6378
@property
64-
def vmem(self) -> "XVariable":
65-
return self.var(1, "vmem")
79+
def xrn(self) -> "XXpr":
80+
return self.xpr(0, "xrn")
81+
82+
@property
83+
def xrm(self) -> "XXpr":
84+
return self.xpr(1, "xrm")
6685

6786
@property
6887
def xmem(self) -> "XXpr":
6988
return self.xpr(2, "xmem")
7089

90+
@property
91+
def is_xmem_ok(self) -> bool:
92+
return self.is_xpr_ok(2)
93+
7194
@property
7295
def xrmem(self) -> "XXpr":
7396
return self.xpr(3, "xrmem")
7497

98+
@property
99+
def is_xrmem_ok(self) -> bool:
100+
return self.is_xpr_ok(3)
101+
102+
@property
103+
def cxrmem(self) -> "XXpr":
104+
return self.cxpr(0, "cxrmem")
105+
106+
@property
107+
def is_cxrmem_ok(self) -> bool:
108+
return self.is_cxpr_ok(0)
109+
75110
@property
76111
def xaddr(self) -> "XXpr":
77112
return self.xpr(4, "xaddr")
78113

79114
@property
80-
def is_xrmem_unknown(self) -> bool:
81-
return self.xdata.xprs_r[3] is None
115+
def is_xaddr_ok(self) -> bool:
116+
return self.is_xpr_ok(4)
117+
118+
@property
119+
def xxaddr(self) -> "XXpr":
120+
return self.xpr(5, "xxaddr")
121+
122+
@property
123+
def is_xxaddr_ok(self) -> bool:
124+
return self.is_xpr_ok(5)
125+
126+
@property
127+
def cxaddr(self) -> "XXpr":
128+
return self.cxpr(1, "cxaddr")
82129

83130
@property
84-
def is_address_known(self) -> bool:
85-
return self.xdata.xprs_r[4] is not None
131+
def is_cxaddr_ok(self) -> bool:
132+
return self.is_cxpr_ok(1)
86133

87134
@property
88135
def annotation(self) -> str:
89136
wbu = self.writeback_update()
90-
if self.is_ok:
91-
assignment = str(self.vrt) + " := " + str(self.xrmem)
92-
elif self.is_xrmem_unknown and self.is_address_known:
93-
assignment = str(self.vrt) + " := *(" + str(self.xaddr) + ")"
137+
if self.is_cxrmem_ok:
138+
crhs = str(self.cxrmem)
139+
elif self.is_cxaddr_ok:
140+
crhs = "*(" + str(self.cxaddr) + ")"
141+
else:
142+
crhs = "None"
143+
cx = " (C: " + crhs + ")"
144+
addr = str(self.xxaddr if self.is_xxaddr_ok else self.xaddr)
145+
caddr = str(self.cxaddr if self.is_cxaddr_ok else "None")
146+
caddr = " (addr: " + addr + "; C: " + caddr + ")"
147+
if self.is_ok or self.is_xrmem_ok:
148+
assignment = str(self.vrt) + " := " + str(self.xrmem) + cx + caddr
149+
elif self.is_xaddr_ok:
150+
assignment = (
151+
str(self.vrt) + " := *(" + str(self.xaddr) + ")" + cx + caddr)
94152
else:
95153
assignment = "Error value"
96154
return self.add_instruction_condition(assignment) + wbu
@@ -109,27 +167,14 @@ class ARMLoadRegisterHalfword(ARMOpcode):
109167
args[3]: index of memory location in armdictionary
110168
args[4]: is-wide (thumb)
111169
112-
xdata format: a:vxxxxrrrdh
113-
--------------------------
114-
vars[0]: lhs
115-
vars[1]: memory location expressed as a variable
116-
xprs[0]: value in rn
117-
xprs[1]: value in rm
118-
xprs[2]: value in memory location
119-
xprs[3]: value in memory location (simplified)
120-
xprs[4]: address of memory location
170+
xdata format:
171+
-------------
121172
rdefs[0]: reaching definitions rn
122173
rdefs[1]: reaching definitions rm
123174
rdefs[2]: reaching definitions memory location
124175
rdefs[3..]: reaching definitions for memory value
125176
uses[0]: use of lhs
126177
useshigh[0]: use of lhs at high level
127-
128-
optional:
129-
vars[1]: lhs base register (if base update)
130-
131-
xprs[.]: instruction condition (if has condition)
132-
xprs[.]: new address for base register
133178
"""
134179

135180
def __init__(self, d: "ARMDictionary", ixval: IndexedTableValue) -> None:
@@ -149,13 +194,20 @@ def opargs(self) -> List[ARMOperand]:
149194
return [self.armd.arm_operand(self.args[i]) for i in [0, 1, 2, 3]]
150195

151196
def lhs(self, xdata: InstrXData) -> List[XVariable]:
152-
return [xdata.vars[0]]
197+
xd = ARMLoadRegisterHalfwordXData(xdata)
198+
return [xd.vrt]
153199

154200
def is_load_instruction(self, xdata: InstrXData) -> bool:
155201
return True
156202

157203
def rhs(self, xdata: InstrXData) -> List[XXpr]:
158-
return [xdata.xprs[1]]
204+
xd = ARMLoadRegisterHalfwordXData(xdata)
205+
if xd.is_xrmem_ok:
206+
return [xd.xrmem]
207+
elif xd.is_xmem_ok:
208+
return [xd.xmem]
209+
else:
210+
return []
159211

160212
def annotation(self, xdata: InstrXData) -> str:
161213
return ARMLoadRegisterHalfwordXData(xdata).annotation
@@ -189,38 +241,63 @@ def ast_prov(
189241

190242
# high-level assignment
191243

244+
def has_cast() -> bool:
245+
return (
246+
astree.has_register_variable_intro(iaddr)
247+
and astree.get_register_variable_intro(iaddr).has_cast())
248+
249+
lhs = xd.vrt
250+
192251
if xd.is_ok:
193-
lhs = xd.vrt
194-
rhs = xd.xrmem
195-
xaddr = xd.xaddr
196-
hl_lhs = XU.xvariable_to_ast_lval(lhs, xdata, iaddr, astree, rhs=rhs)
197-
hl_rhs = XU.xxpr_to_ast_def_expr(
198-
rhs, xdata, iaddr, astree, memaddr=xaddr, size=2)
252+
rhs = xd.cxrmem
253+
rhsval = None if has_cast() else xd.cxrmem
254+
hl_lhs = XU.xvariable_to_ast_lval(
255+
lhs, xdata, iaddr, astree, rhs=rhsval)
256+
hl_rhs = XU.xxpr_to_ast_def_expr(rhs, xdata, iaddr, astree)
257+
258+
elif xd.is_cxaddr_ok:
259+
cxaddr = xd.cxaddr
260+
hl_lhs = XU.xvariable_to_ast_lval(lhs, xdata, iaddr, astree)
261+
hl_rhs = XU.xmemory_dereference_lval_expr(
262+
cxaddr, xdata, iaddr, astree)
199263

200-
elif xd.is_xrmem_unknown and xd.is_address_known:
264+
elif xd.is_xaddr_ok:
201265
xaddr = xd.xaddr
202-
lhs = xd.vrt
203266
hl_lhs = XU.xvariable_to_ast_lval(lhs, xdata, iaddr, astree)
204267
hl_rhs = XU.xmemory_dereference_lval_expr(
205-
xaddr, xdata, iaddr, astree, size=2)
268+
xaddr, xdata, iaddr, astree)
269+
270+
chklogger.logger.warning(
271+
"LDRH: Unable to use a C expression for rhs. Fall back to "
272+
+ "native byte-based address: %s to form rhs %s at address %s",
273+
str(xaddr), str(hl_rhs), iaddr)
206274

207275
else:
208276
chklogger.logger.error(
209277
"LDRH: both memory value and address values are error values "
210278
+ "at address %s: ", iaddr)
211-
return ([], [])
279+
return ([], (ll_pre + [ll_assign] + ll_post))
280+
212281

213282
rdefs = xdata.reachingdefs
214283
defuses = xdata.defuses
215284
defuseshigh = xdata.defuseshigh
216285

286+
if has_cast():
287+
lhstype = hl_lhs.ctype(astree.ctyper)
288+
if lhstype is not None:
289+
hl_rhs = astree.mk_cast_expr(lhstype, hl_rhs)
290+
217291
hl_assign = astree.mk_assign(
218292
hl_lhs,
219293
hl_rhs,
220294
iaddr=iaddr,
221295
bytestring=bytestring,
222296
annotations=annotations)
223297

298+
if has_cast():
299+
astree.add_expose_instruction(hl_assign.instrid)
300+
224301
astree.add_instr_mapping(hl_assign, ll_assign)
225302
astree.add_instr_address(hl_assign, [iaddr])
226303
astree.add_expr_mapping(hl_rhs, ll_rhs)
@@ -245,7 +322,7 @@ def ast_prov(
245322
ll_assigns: List[AST.ASTInstruction] = [ll_assign, ll_addr_assign]
246323

247324
basereg = xd.get_base_update_var()
248-
newaddr = xd.get_base_update_xpr()
325+
newaddr = xd.get_base_update_cxpr()
249326
hl_addr_lhs = XU.xvariable_to_ast_lval(basereg, xdata, iaddr, astree)
250327
hl_addr_rhs = XU.xxpr_to_ast_def_expr(newaddr, xdata, iaddr, astree)
251328

0 commit comments

Comments
 (0)