def _build_flow_warp(state, addr, instruction): warp = nodes.UnconditionalWarp() warp.type = nodes.UnconditionalWarp.T_FLOW warp.target = state._warp_in_block(addr + 1) opcode = instruction.opcode shift = 1 if opcode in (ins.FORI.opcode, ins.UCLO.opcode) else 0 return warp, shift
def _build_conditional_warp(state, last_addr, instructions): condition = instructions[-2] condition_addr = last_addr - 1 warp = nodes.ConditionalWarp() if condition.opcode in (ins.ISTC.opcode, ins.ISFC.opcode): expression = _build_unary_expression(state, condition_addr, condition) setattr(warp, "_slot", condition.A) elif condition.opcode >= ins.IST.opcode: expression = _build_unary_expression(state, condition_addr, condition) setattr(warp, "_slot", condition.CD) else: expression = _build_comparison_expression(state, condition_addr, condition) warp.condition = expression jump = instructions[-1] jump_addr = last_addr destination = get_jump_destination(jump_addr, jump) # A condition is inverted during the preparation phase above warp.false_target = state._warp_in_block(destination) warp.true_target = state._warp_in_block(jump_addr + 1) shift = 2 if destination == (jump_addr + 1) \ and condition.opcode not in (ins.ISTC.opcode, ins.ISFC.opcode): # This is an empty 'then' or 'else'. The simplest way to handle it is # to insert a Block containing just a no-op statement. block = nodes.Block() block.first_address = jump_addr + 1 block.last_address = block.first_address block.index = warp.true_target.index block.warpins_count = 1 setattr(block, "_last_body_addr", block.last_address - shift) block.warp = nodes.UnconditionalWarp() block.warp.type = nodes.UnconditionalWarp.T_FLOW block.warp.target = warp.true_target setattr(block.warp, "_addr", block.last_address - shift + 1) state.blocks.insert(state.blocks.index(warp.true_target), block) warp.true_target = block _create_no_op(state, jump_addr, block) return warp, shift
def _build_unconditional_warp(state, addr, instruction): warp = nodes.UnconditionalWarp() warp.type = nodes.UnconditionalWarp.T_JUMP opcode = instruction.opcode warp.is_uclo = opcode == ins.UCLO.opcode if warp.is_uclo and instruction.CD == 0: # Not a jump return _build_flow_warp(state, addr, instruction) else: destination = get_jump_destination(addr, instruction) warp.target = state._warp_in_block(destination) return warp, 1
def _unwarp_loops(blocks, repeat_until): loops = _find_all_loops(blocks, repeat_until) if len(loops) == 0: return blocks fixed = _cleanup_breaks_and_if_ends(loops, blocks) for start, end in fixed: start_index = blocks.index(start) end_index = blocks.index(end) if repeat_until: body = blocks[start_index:end_index] else: body = blocks[start_index + 1:end_index] loop = _unwarp_loop(start, end, body) body = loop.statements.contents block = nodes.Block() block.first_address = body[0].first_address block.last_address = body[-1].last_address block.index = start.index + 1 block.contents.append(loop) block.warp = nodes.UnconditionalWarp() block.warp.type = nodes.UnconditionalWarp.T_FLOW block.warp.target = end _replace_targets(blocks, body[0], block) _set_end(body[-1]) _unwarp_breaks(start, body, end) blocks = blocks[:start_index + 1] + [block] + blocks[end_index:] return blocks
def _set_flow_to(block, target): block.warp = nodes.UnconditionalWarp() block.warp.type = nodes.UnconditionalWarp.T_FLOW block.warp.target = target