8 log_to_c_h = logging.getLogger(
"ir_helper")
9 console_handler = logging.StreamHandler()
10 console_handler.setFormatter(logging.Formatter(
"%(levelname)-5s: %(message)s"))
11 log_to_c_h.addHandler(console_handler)
12 log_to_c_h.setLevel(logging.WARN)
15 translator = Translator.to_language(
"C")
19 for size
in [8, 16, 32, 64]:
20 prefetch_id_size[size] = []
22 name =
'pfmem%.2d_%d' % (size, i)
23 c = m2_expr.ExprId(name, size)
26 prefetch_id_size[size].append(c)
30 for x
in arch.regs.all_regs_ids + prefetch_id:
31 arch.id2Cid[x] = m2_expr.ExprId(
'((vm_cpu_t*)jitcpu->cpu)->' + str(x), x.size)
35 for x
in arch.regs.all_regs_ids + prefetch_id:
36 arch.id2newCid[x] = m2_expr.ExprId(
'((vm_cpu_t*)jitcpu->cpu)->%s_new' % x, x.size)
40 return e.replace_expr(arch.id2Cid)
44 return e.replace_expr(arch.id2newCid)
47 mask_int = 0xffffffffffffffff
50 pre_instr_test_exception =
r"""
51 // pre instruction test exception
52 if (VM_exception_flag) {
54 return JIT_RET_EXCEPTION;
59 code_exception_fetch_mem_at_instr =
r"""
60 // except fetch mem at instr
61 if (VM_exception_flag & EXCEPT_DO_NOT_UPDATE_PC) {
63 return JIT_RET_EXCEPTION;
66 code_exception_fetch_mem_post_instr =
r"""
67 // except fetch mem post instr
68 if (VM_exception_flag) {
70 return JIT_RET_EXCEPTION;
75 code_exception_fetch_mem_at_instr_noautomod =
r"""
76 // except fetch mem at instr noauto
77 if ((VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) & EXCEPT_DO_NOT_UPDATE_PC) {
79 return JIT_RET_EXCEPTION;
82 code_exception_fetch_mem_post_instr_noautomod =
r"""
83 // except post instr noauto
84 if (VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) {
86 return JIT_RET_EXCEPTION;
91 code_exception_at_instr =
r"""
93 if (CPU_exception_flag && CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) {
95 return JIT_RET_EXCEPTION;
99 code_exception_post_instr =
r"""
101 if (CPU_exception_flag) {
102 if (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) {
108 return JIT_RET_EXCEPTION;
113 code_exception_at_instr_noautomod =
r"""
114 if ((CPU_exception_flag & ~EXCEPT_CODE_AUTOMOD) && (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP)) {
116 return JIT_RET_EXCEPTION;
120 code_exception_post_instr_noautomod =
r"""
121 if (CPU_exception_flag & ~EXCEPT_CODE_AUTOMOD) {
122 if (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) {
128 return JIT_RET_EXCEPTION;
132 goto_local_code =
r"""
133 if (BlockDst->is_local) {
134 goto *local_labels[BlockDst->address];
137 return JIT_RET_NO_EXCEPTION;
141 my_size_mask = {1: 1, 2: 3, 3: 7, 7: 0x7f,
145 64: 0xFFFFFFFFFFFFFFFFL}
147 exception_flags = m2_expr.ExprId(
'exception_flags', 32)
152 if not isinstance(src, m2_expr.Expr):
153 src = m2_expr.ExprInt_from(dst, src)
154 e = m2_expr.ExprAff(dst, src.zeroExtend(dst.size))
159 return 'Resolve_dst(BlockDst, 0x%X, 0)' % (e.arg)
162 if e.name.name.startswith(
"lbl_gen_"):
164 return 'Resolve_dst(BlockDst, 0x%X, 1)'%(e.name.index)
166 return 'Resolve_dst(BlockDst, 0x%X, 0)'%(e.name.offset)
169 return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(
patch_c_id(ir_arch.arch, e)))
172 return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(
patch_c_id(ir_arch.arch, e)))
175 return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(
patch_c_id(ir_arch.arch, e)))
178 if isinstance(e, m2_expr.ExprInt):
180 elif isinstance(e, m2_expr.ExprId)
and isinstance(e.name,
183 elif isinstance(e, m2_expr.ExprId):
185 elif isinstance(e, m2_expr.ExprMem):
193 if isinstance(e, m2_expr.ExprCond):
194 dst_cond_c = translator.from_expr(
patch_c_id(ir_arch.arch, e.cond))
195 out.append(
"if (%s)"%dst_cond_c)
203 def Expr2C(ir_arch, l, exprs, gen_exception_code=False):
205 out = [
"// %s" % (l)]
211 prefect_index = {8: 0, 16: 0, 32: 0, 64: 0}
214 e =
set_pc(ir_arch, l.offset & mask_int)
219 set_exception_flags =
False
221 assert isinstance(e, m2_expr.ExprAff)
222 assert not isinstance(e.dst, m2_expr.ExprOp)
223 if isinstance(e.dst, m2_expr.ExprId):
224 if not e.dst
in dst_dict:
226 dst_dict[e.dst].append(e)
230 ops = m2_expr.get_expr_ops(e)
231 if set([
'umod',
'udiv']).intersection(ops):
232 set_exception_flags =
True
233 if e.dst == exception_flags:
234 set_exception_flags =
True
238 rs = e.src.get_r(mem_read=
True)
240 if (
not isinstance(r, m2_expr.ExprMem))
or r
in src_mem:
243 index = prefect_index[r.size]
244 prefect_index[r.size] += 1
245 pfmem = prefetch_id_size[r.size][index]
248 for dst, exs
in dst_dict.items():
253 log_to_c_h.debug(
'warning: detected multi dst to same id')
254 log_to_c_h.debug(
'\t'.join([str(x)
for x
in exs]))
259 mem_k = src_mem.keys()
262 str_src = translator.from_expr(
patch_c_id(ir_arch.arch, k))
263 str_dst = translator.from_expr(
patch_c_id(ir_arch.arch, src_mem[k]))
264 out.append(
'%s = %s;' % (str_dst, str_src))
266 for k, v
in src_mem.items():
270 src, dst = e.src, e.dst
272 src = src.replace_expr(src_w_len)
273 if dst
is ir_arch.IRDst:
278 str_src = translator.from_expr(
patch_c_id(ir_arch.arch, src))
279 str_dst = translator.from_expr(
patch_c_id(ir_arch.arch, dst))
283 if isinstance(dst, m2_expr.ExprId):
284 id_to_update.append(dst)
286 if dst
in ir_arch.arch.regs.regs_flt_expr:
288 out.append(
'%s = (%s);' % (str_dst, str_src))
290 out.append(
'%s = (%s)&0x%X;' % (str_dst, str_src,
291 my_size_mask[src.size]))
292 elif isinstance(dst, m2_expr.ExprMem):
294 str_dst = str_dst.replace(
'MEM_LOOKUP',
'MEM_WRITE')
295 out_mem.append(
'%s, %s);' % (str_dst[:-1], str_src))
297 if e.dst == ir_arch.arch.pc[ir_arch.attrib]:
299 out_pc += [
"return JIT_RET_NO_EXCEPTION;"]
306 if gen_exception_code:
308 e =
set_pc(ir_arch, l.offset & mask_int)
309 s1 =
"%s" % translator.from_expr(
patch_c_id(ir_arch.arch, e))
310 s1 +=
';\n Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int)
311 out.append(code_exception_fetch_mem_at_instr_noautomod % s1)
312 if set_exception_flags:
313 e =
set_pc(ir_arch, l.offset & mask_int)
314 s1 =
"%s" % translator.from_expr(
patch_c_id(ir_arch.arch, e))
315 s1 +=
';\n Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int)
316 out.append(code_exception_at_instr_noautomod % s1)
318 for i
in id_to_update:
319 if i
is ir_arch.IRDst:
321 out.append(
'%s = %s;' %
326 if gen_exception_code:
327 if set_exception_flags:
329 post_instr.append(
"if (VM_exception_flag) { " +
330 "/*pc = 0x%X; */return JIT_RET_EXCEPTION; }" % (l.offset))
332 e =
set_pc(ir_arch, l.offset & mask_int)
333 s1 =
"%s" % translator.from_expr(
patch_c_id(ir_arch.arch, e))
334 s1 +=
';\n Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int)
335 e =
set_pc(ir_arch, (l.offset + l.l) & mask_int)
336 s2 =
"%s" % translator.from_expr(
patch_c_id(ir_arch.arch, e))
337 s2 +=
';\n Resolve_dst(BlockDst, 0x%X, 0)'%((l.offset + l.l) & mask_int)
339 code_exception_post_instr_noautomod % (s1, s2))
342 if l.additional_info.except_on_instr:
345 offset = l.offset + l.l
347 e =
set_pc(ir_arch, offset & mask_int)
348 s1 =
"%s" % translator.from_expr(
patch_c_id(ir_arch.arch, e))
349 s1 +=
';\n Resolve_dst(BlockDst, 0x%X, 0)'%(offset & mask_int)
351 code_exception_fetch_mem_post_instr_noautomod % (s1))
354 return out, post_instr, post_instr + out_pc
358 if not isinstance(e, m2_expr.ExprId):
360 if not isinstance(e.name, asmbloc.asm_label):
362 return m2_expr.ExprInt_from(e, e.name.offset)
366 if isinstance(e, m2_expr.ExprId):
367 if isinstance(e.name, asmbloc.asm_label):
368 src_c =
'PyString_FromStringAndSize("%s", %d)' % (
369 e.name.name, len(e.name.name))
371 src_c =
'PyLong_FromUnsignedLongLong(%s)' %
patch_c_id(arch, e)
373 raise NotImplementedError(
'unknown type for e: %s' %
type(e))
377 def ir2C(ir_arch, irbloc, lbl_done,
378 gen_exception_code=
False, log_mn=
False, log_regs=
False):
382 out.append([
"%s:" % irbloc.label.name])
384 assert len(irbloc.irs) == len(irbloc.lines)
385 for l, exprs
in zip(irbloc.lines, irbloc.irs):
386 if l.offset
not in lbl_done:
387 e =
set_pc(ir_arch, l.offset & mask_int)
388 s1 =
"%s" % translator.from_expr(
patch_c_id(ir_arch.arch, e))
389 s1 +=
';\n Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int)
390 out.append([pre_instr_test_exception % (s1)])
391 lbl_done.add(l.offset)
394 out.append([
r'dump_gpregs(jitcpu->cpu);'])
397 out.append([
'printf("%.8X %s\\n");' % (l.offset, str(l))])
401 c_code, post_instr, _ =
Expr2C(ir_arch, l, exprs, gen_exception_code)
402 out.append(c_code + post_instr)
403 out.append([goto_local_code ] )
407 def irblocs2C(ir_arch, resolvers, label, irblocs,
408 gen_exception_code=
False, log_mn=
False, log_regs=
False):
411 lbls = [b.label
for b
in irblocs]
414 if l.name.startswith(
'lbl_gen_'):
415 l.index = int(l.name[8:], 16)
417 lbl_index_min, lbl_index_max = 0, 0
418 lbls_index = [l.index
for l
in lbls
if hasattr(l,
'index')]
419 lbls_local.sort(key=
lambda x:x.index)
422 lbl_index_min = min(lbls_index)
423 lbl_index_max = max(lbls_index)
425 l.index -= lbl_index_min
427 out.append(
"void* local_labels[] = {%s};"%(
', '.join([
"&&%s"%l.name
for l
in lbls_local])))
429 out.append(
"goto %s;" % label.name)
430 bloc_labels = [x.label
for x
in irblocs]
431 assert label
in bloc_labels
433 lbl_done = set([
None])
435 for irbloc
in irblocs:
437 if irbloc.label.offset
is None:
438 b_out =
ir2C(ir_arch, irbloc, lbl_done, gen_exception_code)
441 ir_arch, irbloc, lbl_done, gen_exception_code, log_mn, log_regs)
def gen_resolve_dst_simple