/* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * This software may be used and distributed according to the terms of the GNU * General Public License version 2 or any later version. */ #include #include #include "common/assert.h" #include "common/common_types.h" #include "dynarmic/A64/config.h" #include "frontend/A64/location_descriptor.h" #include "frontend/A64/translate/translate.h" #include "frontend/ir/basic_block.h" #include "ir_opt/passes.h" namespace Dynarmic { namespace Optimization { void A64MergeInterpretBlocksPass(IR::Block& block, A64::UserCallbacks* cb) { const auto is_interpret_instruction = [cb](A64::LocationDescriptor location) { const u32 instruction = cb->MemoryReadCode(location.PC()); IR::Block new_block{location}; A64::TranslateSingleInstruction(new_block, location, instruction); if (!new_block.Instructions().empty()) return false; const IR::Terminal terminal = new_block.GetTerminal(); if (auto term = boost::get(&terminal)) { return term->next == location; } return false; }; IR::Terminal terminal = block.GetTerminal(); auto term = boost::get(&terminal); if (!term) return; A64::LocationDescriptor location{term->next}; size_t num_instructions = 1; while (is_interpret_instruction(location.AdvancePC(static_cast(num_instructions * 4)))) { num_instructions++; } term->num_instructions = num_instructions; block.ReplaceTerminal(terminal); block.CycleCount() += num_instructions - 1; } } // namespace Optimization } // namespace Dynarmic