aoqi@1: /* aoqi@1: * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@1: * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved. aoqi@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@1: * aoqi@1: * This code is free software; you can redistribute it and/or modify it aoqi@1: * under the terms of the GNU General Public License version 2 only, as aoqi@1: * published by the Free Software Foundation. aoqi@1: * aoqi@1: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@1: * version 2 for more details (a copy is included in the LICENSE file that aoqi@1: * accompanied this code). aoqi@1: * aoqi@1: * You should have received a copy of the GNU General Public License version aoqi@1: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@1: * aoqi@1: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@1: * or visit www.oracle.com if you need additional information or have any aoqi@1: * questions. aoqi@1: * aoqi@1: */ aoqi@1: aoqi@1: #include "precompiled.hpp" aoqi@1: #include "asm/macroAssembler.hpp" aoqi@1: #include "code/relocInfo.hpp" aoqi@1: #include "nativeInst_mips.hpp" aoqi@1: #include "oops/oop.inline.hpp" aoqi@1: #include "runtime/safepoint.hpp" aoqi@1: aoqi@1: aoqi@1: void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { aoqi@1: #ifdef _LP64 aoqi@1: x += o; aoqi@1: typedef Assembler::WhichOperand WhichOperand; aoqi@1: WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm, call32, narrow oop aoqi@1: assert(which == Assembler::disp32_operand || aoqi@1: which == Assembler::narrow_oop_operand || aoqi@1: which == Assembler::imm_operand, "format unpacks ok"); aoqi@1: if (which == Assembler::imm_operand) { aoqi@1: if (verify_only) { aoqi@1: assert(nativeMovConstReg_at(addr())->data() == (long)x, "instructions must match"); aoqi@1: } else { aoqi@1: nativeMovConstReg_at(addr())->set_data((intptr_t)(x)); aoqi@1: } aoqi@1: } else if (which == Assembler::narrow_oop_operand) { aoqi@1: // both compressed oops and compressed classes look the same aoqi@1: if (Universe::heap()->is_in_reserved((oop)x)) { aoqi@1: if (verify_only) { aoqi@1: assert(nativeMovConstReg_at(addr())->data() == (long)oopDesc::encode_heap_oop((oop)x), "instructions must match"); aoqi@1: } else { aoqi@1: nativeMovConstReg_at(addr())->set_data((intptr_t)(oopDesc::encode_heap_oop((oop)x))); aoqi@1: } aoqi@1: } else { aoqi@1: if (verify_only) { aoqi@1: assert(nativeMovConstReg_at(addr())->data() == (long)Klass::encode_klass((Klass*)x), "instructions must match"); aoqi@1: } else { aoqi@1: nativeMovConstReg_at(addr())->set_data((intptr_t)(Klass::encode_klass((Klass*)x))); aoqi@1: } aoqi@1: } aoqi@1: } else { aoqi@1: // Note: Use runtime_call_type relocations for call32_operand. aoqi@1: assert(0, "call32_operand not supported in MIPS64"); aoqi@1: } aoqi@1: #else aoqi@1: if (verify_only) { aoqi@1: assert(*pd_address_in_code() == (x + o), "instructions must match"); aoqi@1: } else { aoqi@1: *pd_address_in_code() = x + o; aoqi@1: } aoqi@1: #endif // AMD64 aoqi@1: } aoqi@1: aoqi@1: aoqi@1: //NOTICE HERE, this relocate is not need for MIPS, since MIPS USE abosolutly target, aoqi@1: //Maybe We should FORGET CALL RELOCATION aoqi@1: address Relocation::pd_call_destination(address orig_addr) { aoqi@1: intptr_t adj = 0; aoqi@1: NativeInstruction* ni = nativeInstruction_at(addr()); aoqi@1: if (ni->is_call()) { aoqi@1: return nativeCall_at(addr())->destination() + adj; aoqi@1: } else if (ni->is_jump()) { aoqi@1: //return nativeJump_at(addr())->jump_destination() + adj; aoqi@1: return nativeGeneralJump_at(addr())->jump_destination() + adj; aoqi@1: } else if (ni->is_cond_jump()) { aoqi@1: return nativeCondJump_at(addr())->jump_destination() +adj; aoqi@1: } else { aoqi@1: ShouldNotReachHere(); aoqi@1: return NULL; aoqi@1: } aoqi@1: } aoqi@1: aoqi@1: aoqi@1: void Relocation::pd_set_call_destination(address x) { aoqi@1: NativeInstruction* ni = nativeInstruction_at(addr()); aoqi@1: if (ni->is_call()) { aoqi@1: nativeCall_at(addr())->set_destination(x); aoqi@1: } else if (ni->is_jump()) aoqi@1: //NativeJump* nj = nativeJump_at(addr()); aoqi@1: nativeGeneralJump_at(addr())->set_jump_destination(x); aoqi@1: else if (ni->is_cond_jump()) aoqi@1: nativeCondJump_at(addr())->set_jump_destination(x); aoqi@1: else aoqi@1: { ShouldNotReachHere(); } aoqi@1: aoqi@1: // Unresolved jumps are recognized by a destination of -1 aoqi@1: // However 64bit can't actually produce such an address aoqi@1: // and encodes a jump to self but jump_destination will aoqi@1: // return a -1 as the signal. We must not relocate this aoqi@1: // jmp or the ic code will not see it as unresolved. aoqi@1: /* aoqi@1: if (nj->jump_destination() == (address) -1) { aoqi@1: x = addr(); // jump to self aoqi@1: } aoqi@1: nj->set_jump_destination(x); aoqi@1: } else if (ni->is_cond_jump()) { aoqi@1: // %%%% kludge this, for now, until we get a jump_destination method aoqi@1: address old_dest = nativeGeneralJump_at(addr())->jump_destination(); aoqi@1: address disp = Assembler::locate_operand(addr(), Assembler::call32_operand); aoqi@1: *(jint*)disp += (x - old_dest); aoqi@1: } else if (ni->is_mov_literal64()) { aoqi@1: ((NativeMovConstReg*)ni)->set_data((intptr_t)x); aoqi@1: } else { aoqi@1: ShouldNotReachHere(); aoqi@1: } aoqi@1: */ aoqi@1: } aoqi@1: aoqi@1: aoqi@1: address* Relocation::pd_address_in_code() { aoqi@1: //ShouldNotReachHere(); aoqi@1: return (address*)addr(); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: address Relocation::pd_get_address_from_code() { aoqi@1: tty->print_cr("%s: %d", __func__, __LINE__); //aoqi_test aoqi@1: NativeMovConstReg* ni = nativeMovConstReg_at(addr()); aoqi@1: return (address)ni->data(); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: /* aoqi@1: int Relocation::pd_breakpoint_size() { aoqi@1: // minimum breakpoint size, in short words aoqi@1: return NativeIllegalInstruction::instruction_size / sizeof(short); aoqi@1: } aoqi@1: aoqi@1: void Relocation::pd_swap_in_breakpoint(address x, short* instrs, int instrlen) { aoqi@1: Untested("pd_swap_in_breakpoint"); aoqi@1: if (instrs != NULL) { aoqi@1: assert(instrlen * sizeof(short) == NativeIllegalInstruction::instruction_size, "enough instrlen in reloc. data"); aoqi@1: for (int i = 0; i < instrlen; i++) { aoqi@1: instrs[i] = ((short*)x)[i]; aoqi@1: } aoqi@1: } aoqi@1: NativeIllegalInstruction::insert(x); aoqi@1: } aoqi@1: aoqi@1: void Relocation::pd_swap_out_breakpoint(address x, short* instrs, int instrlen) { aoqi@1: Untested("pd_swap_out_breakpoint"); aoqi@1: assert(NativeIllegalInstruction::instruction_size == sizeof(short), "right address unit for update"); aoqi@1: NativeInstruction* ni = nativeInstruction_at(x); aoqi@1: *(short*)ni->addr_at(0) = instrs[0]; aoqi@1: } aoqi@1: */ aoqi@1: aoqi@1: void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { aoqi@1: // Unimplemented(); aoqi@1: } aoqi@1: aoqi@1: void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { aoqi@1: // Unimplemented(); aoqi@1: } aoqi@1: aoqi@1: void internal_pc_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { aoqi@1: address target =0; aoqi@1: NativeMovConstReg* ni = nativeMovConstReg_at(addr()); aoqi@1: target = new_addr_for((address)ni->data(), src, dest); aoqi@1: ni->set_data((intptr_t)target); aoqi@1: } aoqi@1: aoqi@1: void metadata_Relocation::pd_fix_value(address x) { aoqi@1: } aoqi@1: