diff --git a/src/cpu/aarch32/vm/nativeInst_aarch32.cpp b/src/cpu/aarch32/vm/nativeInst_aarch32.cpp --- a/src/cpu/aarch32/vm/nativeInst_aarch32.cpp +++ b/src/cpu/aarch32/vm/nativeInst_aarch32.cpp @@ -104,8 +104,16 @@ } bool NativeCall::is_call_before(address return_address) { - return is_at(return_address - NativeImmCall::instruction_size) || - is_at(return_address - NativeCall::instruction_size); + if (NativeTrampolineCall::is_at(return_address - NativeCall::instruction_size)) { + return true; + } else if (NativeMovConstReg::is_at(return_address - NativeCall::instruction_size)) { + NativeMovConstReg *nm = NativeMovConstReg::from(return_address - NativeCall::instruction_size); + address next_instr = nm->next_instruction_address(); + return NativeRegCall::is_at(next_instr) && NativeRegCall::from(next_instr)->destination() == nm->destination(); + } else if (NativeImmCall::is_at(return_address - NativeBranchType::instruction_size)) { + return true; + } + return false; } address NativeCall::next_instruction_address() const { diff --git a/src/cpu/aarch32/vm/nativeInst_aarch32.hpp b/src/cpu/aarch32/vm/nativeInst_aarch32.hpp --- a/src/cpu/aarch32/vm/nativeInst_aarch32.hpp +++ b/src/cpu/aarch32/vm/nativeInst_aarch32.hpp @@ -303,20 +303,6 @@ return NativeCall::from(address); } -inline NativeCall* nativeCall_before(address return_address) { - address call_addr = NULL; - if (NativeCall::is_at(return_address - NativeBranchType::instruction_size)) { - call_addr = return_address - NativeBranchType::instruction_size; - } else if (NativeCall::is_at(return_address - NativeCall::instruction_size)) { - call_addr = return_address - NativeCall::instruction_size; - } else { - ShouldNotReachHere(); - } - - return NativeCall::from(call_addr); -} - - // An interface for accessing/manipulating native moves of the form: // mov[b/w/l/q] [reg + offset], reg (instruction_code_reg2mem) // mov[b/w/l/q] reg, [reg+offset] (instruction_code_mem2reg @@ -505,4 +491,27 @@ inline bool NativeInstruction::is_imm_jump() const { return NativeImmJump::is_at(addr()); } inline bool NativeInstruction::is_reg_jump() const { return NativeRegJump::is_at(addr()); } +inline NativeCall* nativeCall_before(address return_address) { + address call_addr = NULL; + if (NativeTrampolineCall::is_at(return_address - NativeCall::instruction_size)) { + call_addr = return_address - NativeCall::instruction_size; + } else if (NativeMovConstReg::is_at(return_address - NativeCall::instruction_size)) { + NativeMovConstReg *nm = NativeMovConstReg::from(return_address - NativeCall::instruction_size); + address next_instr = nm->next_instruction_address(); + if (NativeRegCall::is_at(next_instr) && + NativeRegCall::from(next_instr)->destination() == nm->destination()) { + call_addr = return_address - NativeCall::instruction_size; + } + } + if (!call_addr) { + if (NativeImmCall::is_at(return_address - NativeBranchType::instruction_size)) { + call_addr = return_address - NativeBranchType::instruction_size; + } else { + ShouldNotReachHere(); + } + } + + return NativeCall::from(call_addr); +} + #endif // CPU_AARCH32_VM_NATIVEINST_AARCH32_HPP