1 /*
   2  * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
   4  * Copyright (c) 2015, Linaro Ltd. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  *
  25  */
  26 
  27 #include "precompiled.hpp"
  28 #include "asm/macroAssembler.hpp"
  29 #include "code/relocInfo.hpp"
  30 #include "nativeInst_aarch32.hpp"
  31 #include "oops/oop.inline.hpp"
  32 #include "runtime/safepoint.hpp"
  33 
  34 void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
  35   int bytes;
  36 
  37   NativeInstruction *ni = NativeInstruction::from(addr());
  38   if (ni->is_mov_const_reg()) {
  39     NativeMovConstReg *nm = NativeMovConstReg::from(addr());
  40     if (verify_only) {
  41       assert(nm->data() == (intptr_t) x, "instructions must match");
  42       return;
  43     }
  44     nm->set_data((intptr_t) x);
  45     bytes = nm->next_instruction_address() - nm->addr();
  46   } else {
  47     ShouldNotReachHere();
  48   }
  49 
  50   ICache::invalidate_range(addr(), bytes);
  51 }
  52 
  53 address Relocation::pd_call_destination(address orig_addr) {
  54   intptr_t adj = 0;
  55   if (orig_addr != NULL) {
  56     // We just moved this call instruction from orig_addr to addr().
  57     // This means its target will appear to have grown by addr() - orig_addr.
  58     adj = -( addr() - orig_addr );
  59   }
  60 
  61   NativeInstruction *ni = NativeInstruction::from(addr());
  62 
  63   // Checking from shortest encoding size to longets,
  64   // to avoid access beyond CodeCache boundary
  65   if (NativeImmCall::is_at(addr())) {
  66     return NativeImmCall::from(addr())->destination() + adj;
  67   } else if (NativeImmJump::is_at(addr())) {
  68     return NativeImmJump::from(addr())->destination() + adj;
  69   } else if (NativeCall::is_at(addr())) {
  70     return NativeCall::from(addr())->destination();
  71   } else if (NativeJump::is_at(addr())) {
  72     return NativeJump::from(addr())->jump_destination();
  73   }
  74 
  75   ShouldNotReachHere();
  76 }
  77 
  78 void Relocation::pd_set_call_destination(address x) {
  79   assert(addr() != x, "call instruction in an infinite loop"); // FIXME what's wrong to _generate_ loop?
  80   NativeInstruction *ni = NativeInstruction::from(addr());
  81 
  82   // Checking from shortest encoding size to longets,
  83   // to avoid access beyond CodeCache boundary
  84   if (NativeImmCall::is_at(addr())) {
  85     NativeImmCall::from(addr())->set_destination(x);
  86   } else if (NativeImmJump::is_at(addr())) {
  87     NativeImmJump::from(addr())->set_destination(x);
  88   } else if (NativeCall::is_at(addr())) {
  89     NativeCall::from(addr())->set_destination(x);
  90   } else if (NativeJump::is_at(addr())) {
  91     NativeJump::from(addr())->set_jump_destination(x);
  92   } else {
  93     ShouldNotReachHere();
  94   }
  95 
  96   assert(pd_call_destination(addr()) == x, "fail in reloc");
  97 }
  98 
  99 address* Relocation::pd_address_in_code() {
 100   ShouldNotCallThis();
 101   return NULL;
 102 }
 103 
 104 address Relocation::pd_get_address_from_code() {
 105   ShouldNotCallThis();
 106   return NULL;
 107 }
 108 
 109 void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
 110   NativeInstruction *ni = NativeInstruction::from(addr());
 111   if (ni->is_mov_const_reg()) {
 112     address old_addr = old_addr_for(addr(), src, dest);
 113     NativeMovConstReg *nm2 = NativeMovConstReg::from(old_addr);
 114     NativeMovConstReg::from(addr())->set_data(nm2->data());
 115   }
 116 }
 117 
 118 void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest)  {
 119   NativeInstruction *ni = NativeInstruction::from(addr());
 120   if (ni->is_mov_const_reg()) {
 121     address old_addr = old_addr_for(addr(), src, dest);
 122     NativeMovConstReg *nm2 = NativeMovConstReg::from(old_addr);
 123     NativeMovConstReg::from(addr())->set_data(nm2->data());
 124   }
 125 }
 126 
 127 void metadata_Relocation::pd_fix_value(address x) {
 128 }