diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 879eca9c..0cb4ccd8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ set(SRCS frontend/translate/translate_arm/synchronization.cpp frontend/translate/translate_arm/vfp2.cpp frontend/translate/translate_thumb.cpp + ir_opt/constant_propagation_pass.cpp ir_opt/dead_code_elimination_pass.cpp ir_opt/get_set_elimination_pass.cpp ir_opt/verification_pass.cpp diff --git a/src/backend_x64/interface_x64.cpp b/src/backend_x64/interface_x64.cpp index 78123370..5511a019 100644 --- a/src/backend_x64/interface_x64.cpp +++ b/src/backend_x64/interface_x64.cpp @@ -105,6 +105,7 @@ private: IR::Block ir_block = Arm::Translate(descriptor, callbacks.memory.ReadCode); Optimization::GetSetElimination(ir_block); + Optimization::ConstantPropagation(ir_block, callbacks.memory); Optimization::DeadCodeElimination(ir_block); Optimization::VerificationPass(ir_block); return emitter.Emit(ir_block); diff --git a/src/ir_opt/constant_propagation_pass.cpp b/src/ir_opt/constant_propagation_pass.cpp new file mode 100644 index 00000000..cb925f9a --- /dev/null +++ b/src/ir_opt/constant_propagation_pass.cpp @@ -0,0 +1,73 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 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 "frontend/ir/basic_block.h" +#include "frontend/ir/opcodes.h" +#include "ir_opt/passes.h" + +namespace Dynarmic { +namespace Optimization { + +void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_callbacks) { + for (auto& inst : block) { + if (!inst.AreAllArgsImmediates()) + continue; + + switch (inst.GetOpcode()) { + case IR::Opcode::ReadMemory8: { + u32 vaddr = inst.GetArg(0).GetU32(); + if (memory_callbacks.IsReadOnlyMemory(vaddr)) { + u8 value_from_memory = memory_callbacks.Read8(vaddr); + inst.ReplaceUsesWith(IR::Value{value_from_memory}); + } + break; + } + case IR::Opcode::ReadMemory16: { + u32 vaddr = inst.GetArg(0).GetU32(); + if (memory_callbacks.IsReadOnlyMemory(vaddr)) { + u16 value_from_memory = memory_callbacks.Read16(vaddr); + inst.ReplaceUsesWith(IR::Value{value_from_memory}); + } + break; + } + case IR::Opcode::ReadMemory32: { + u32 vaddr = inst.GetArg(0).GetU32(); + if (memory_callbacks.IsReadOnlyMemory(vaddr)) { + u32 value_from_memory = memory_callbacks.Read32(vaddr); + inst.ReplaceUsesWith(IR::Value{value_from_memory}); + } + break; + } + case IR::Opcode::ReadMemory64: { + u32 vaddr = inst.GetArg(0).GetU32(); + if (memory_callbacks.IsReadOnlyMemory(vaddr)) { + u64 value_from_memory = memory_callbacks.Read64(vaddr); + inst.ReplaceUsesWith(IR::Value{value_from_memory}); + } + break; + } + case IR::Opcode::ZeroExtendByteToWord: { + u8 byte = inst.GetArg(0).GetU8(); + u32 value = static_cast(byte); + inst.ReplaceUsesWith(IR::Value{value}); + break; + } + case IR::Opcode::ZeroExtendHalfToWord: { + u16 half = inst.GetArg(0).GetU16(); + u32 value = static_cast(half); + inst.ReplaceUsesWith(IR::Value{value}); + break; + } + default: + break; + } + } +} + +} // namespace Optimization +} // namespace Dynarmic diff --git a/src/ir_opt/passes.h b/src/ir_opt/passes.h index 8d06509c..c861c876 100644 --- a/src/ir_opt/passes.h +++ b/src/ir_opt/passes.h @@ -6,6 +6,8 @@ #pragma once +#include + namespace Dynarmic { namespace IR { class Block; @@ -16,6 +18,7 @@ namespace Dynarmic { namespace Optimization { void GetSetElimination(IR::Block& block); +void ConstantPropagation(IR::Block& block, const UserCallbacks::Memory& memory_callbacks); void DeadCodeElimination(IR::Block& block); void VerificationPass(const IR::Block& block);