src/cpu/sparc/vm/nativeInst_sparc.cpp

changeset 435
a61af66fc99e
child 551
018d5b58dd4f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/cpu/sparc/vm/nativeInst_sparc.cpp	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,989 @@
     1.4 +/*
     1.5 + * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +# include "incls/_precompiled.incl"
    1.29 +# include "incls/_nativeInst_sparc.cpp.incl"
    1.30 +
    1.31 +
    1.32 +void NativeInstruction::set_data64_sethi(address instaddr, intptr_t x) {
    1.33 +  ResourceMark rm;
    1.34 +  CodeBuffer buf(instaddr, 10 * BytesPerInstWord );
    1.35 +  MacroAssembler* _masm = new MacroAssembler(&buf);
    1.36 +  Register destreg;
    1.37 +
    1.38 +  destreg = inv_rd(*(unsigned int *)instaddr);
    1.39 +  // Generate a the new sequence
    1.40 +  Address dest( destreg, (address)x );
    1.41 +  _masm->sethi( dest, true );
    1.42 +  ICache::invalidate_range(instaddr, 7 * BytesPerInstWord);
    1.43 +}
    1.44 +
    1.45 +void NativeInstruction::verify() {
    1.46 +  // make sure code pattern is actually an instruction address
    1.47 +  address addr = addr_at(0);
    1.48 +  if (addr == 0 || ((intptr_t)addr & 3) != 0) {
    1.49 +    fatal("not an instruction address");
    1.50 +  }
    1.51 +}
    1.52 +
    1.53 +void NativeInstruction::print() {
    1.54 +  tty->print_cr(INTPTR_FORMAT ": 0x%x", addr_at(0), long_at(0));
    1.55 +}
    1.56 +
    1.57 +void NativeInstruction::set_long_at(int offset, int i) {
    1.58 +  address addr = addr_at(offset);
    1.59 +  *(int*)addr = i;
    1.60 +  ICache::invalidate_word(addr);
    1.61 +}
    1.62 +
    1.63 +void NativeInstruction::set_jlong_at(int offset, jlong i) {
    1.64 +  address addr = addr_at(offset);
    1.65 +  *(jlong*)addr = i;
    1.66 +  // Don't need to invalidate 2 words here, because
    1.67 +  // the flush instruction operates on doublewords.
    1.68 +  ICache::invalidate_word(addr);
    1.69 +}
    1.70 +
    1.71 +void NativeInstruction::set_addr_at(int offset, address x) {
    1.72 +  address addr = addr_at(offset);
    1.73 +  assert( ((intptr_t)addr & (wordSize-1)) == 0, "set_addr_at bad address alignment");
    1.74 +  *(uintptr_t*)addr = (uintptr_t)x;
    1.75 +  // Don't need to invalidate 2 words here in the 64-bit case,
    1.76 +  // because the flush instruction operates on doublewords.
    1.77 +  ICache::invalidate_word(addr);
    1.78 +  // The Intel code has this assertion for NativeCall::set_destination,
    1.79 +  // NativeMovConstReg::set_data, NativeMovRegMem::set_offset,
    1.80 +  // NativeJump::set_jump_destination, and NativePushImm32::set_data
    1.81 +  //assert (Patching_lock->owned_by_self(), "must hold lock to patch instruction")
    1.82 +}
    1.83 +
    1.84 +bool NativeInstruction::is_zero_test(Register &reg) {
    1.85 +  int x = long_at(0);
    1.86 +  Assembler::op3s temp = (Assembler::op3s) (Assembler::sub_op3 | Assembler::cc_bit_op3);
    1.87 +  if (is_op3(x, temp, Assembler::arith_op) &&
    1.88 +      inv_immed(x) && inv_rd(x) == G0) {
    1.89 +      if (inv_rs1(x) == G0) {
    1.90 +        reg = inv_rs2(x);
    1.91 +        return true;
    1.92 +      } else if (inv_rs2(x) == G0) {
    1.93 +        reg = inv_rs1(x);
    1.94 +        return true;
    1.95 +      }
    1.96 +  }
    1.97 +  return false;
    1.98 +}
    1.99 +
   1.100 +bool NativeInstruction::is_load_store_with_small_offset(Register reg) {
   1.101 +  int x = long_at(0);
   1.102 +  if (is_op(x, Assembler::ldst_op) &&
   1.103 +      inv_rs1(x) == reg && inv_immed(x)) {
   1.104 +    return true;
   1.105 +  }
   1.106 +  return false;
   1.107 +}
   1.108 +
   1.109 +void NativeCall::verify() {
   1.110 +  NativeInstruction::verify();
   1.111 +  // make sure code pattern is actually a call instruction
   1.112 +  if (!is_op(long_at(0), Assembler::call_op)) {
   1.113 +    fatal("not a call");
   1.114 +  }
   1.115 +}
   1.116 +
   1.117 +void NativeCall::print() {
   1.118 +  tty->print_cr(INTPTR_FORMAT ": call " INTPTR_FORMAT, instruction_address(), destination());
   1.119 +}
   1.120 +
   1.121 +
   1.122 +// MT-safe patching of a call instruction (and following word).
   1.123 +// First patches the second word, and then atomicly replaces
   1.124 +// the first word with the first new instruction word.
   1.125 +// Other processors might briefly see the old first word
   1.126 +// followed by the new second word.  This is OK if the old
   1.127 +// second word is harmless, and the new second word may be
   1.128 +// harmlessly executed in the delay slot of the call.
   1.129 +void NativeCall::replace_mt_safe(address instr_addr, address code_buffer) {
   1.130 +  assert(Patching_lock->is_locked() ||
   1.131 +         SafepointSynchronize::is_at_safepoint(), "concurrent code patching");
   1.132 +   assert (instr_addr != NULL, "illegal address for code patching");
   1.133 +   NativeCall* n_call =  nativeCall_at (instr_addr); // checking that it is a call
   1.134 +   assert(NativeCall::instruction_size == 8, "wrong instruction size; must be 8");
   1.135 +   int i0 = ((int*)code_buffer)[0];
   1.136 +   int i1 = ((int*)code_buffer)[1];
   1.137 +   int* contention_addr = (int*) n_call->addr_at(1*BytesPerInstWord);
   1.138 +   assert(inv_op(*contention_addr) == Assembler::arith_op ||
   1.139 +          *contention_addr == nop_instruction() || !VM_Version::v9_instructions_work(),
   1.140 +          "must not interfere with original call");
   1.141 +   // The set_long_at calls do the ICacheInvalidate so we just need to do them in reverse order
   1.142 +   n_call->set_long_at(1*BytesPerInstWord, i1);
   1.143 +   n_call->set_long_at(0*BytesPerInstWord, i0);
   1.144 +   // NOTE:  It is possible that another thread T will execute
   1.145 +   // only the second patched word.
   1.146 +   // In other words, since the original instruction is this
   1.147 +   //    call patching_stub; nop                   (NativeCall)
   1.148 +   // and the new sequence from the buffer is this:
   1.149 +   //    sethi %hi(K), %r; add %r, %lo(K), %r      (NativeMovConstReg)
   1.150 +   // what T will execute is this:
   1.151 +   //    call patching_stub; add %r, %lo(K), %r
   1.152 +   // thereby putting garbage into %r before calling the patching stub.
   1.153 +   // This is OK, because the patching stub ignores the value of %r.
   1.154 +
   1.155 +   // Make sure the first-patched instruction, which may co-exist
   1.156 +   // briefly with the call, will do something harmless.
   1.157 +   assert(inv_op(*contention_addr) == Assembler::arith_op ||
   1.158 +          *contention_addr == nop_instruction() || !VM_Version::v9_instructions_work(),
   1.159 +          "must not interfere with original call");
   1.160 +}
   1.161 +
   1.162 +// Similar to replace_mt_safe, but just changes the destination.  The
   1.163 +// important thing is that free-running threads are able to execute this
   1.164 +// call instruction at all times.  Thus, the displacement field must be
   1.165 +// instruction-word-aligned.  This is always true on SPARC.
   1.166 +//
   1.167 +// Used in the runtime linkage of calls; see class CompiledIC.
   1.168 +void NativeCall::set_destination_mt_safe(address dest) {
   1.169 +  assert(Patching_lock->is_locked() ||
   1.170 +         SafepointSynchronize::is_at_safepoint(), "concurrent code patching");
   1.171 +  // set_destination uses set_long_at which does the ICache::invalidate
   1.172 +  set_destination(dest);
   1.173 +}
   1.174 +
   1.175 +// Code for unit testing implementation of NativeCall class
   1.176 +void NativeCall::test() {
   1.177 +#ifdef ASSERT
   1.178 +  ResourceMark rm;
   1.179 +  CodeBuffer cb("test", 100, 100);
   1.180 +  MacroAssembler* a = new MacroAssembler(&cb);
   1.181 +  NativeCall  *nc;
   1.182 +  uint idx;
   1.183 +  int offsets[] = {
   1.184 +    0x0,
   1.185 +    0xfffffff0,
   1.186 +    0x7ffffff0,
   1.187 +    0x80000000,
   1.188 +    0x20,
   1.189 +    0x4000,
   1.190 +  };
   1.191 +
   1.192 +  VM_Version::allow_all();
   1.193 +
   1.194 +  a->call( a->pc(), relocInfo::none );
   1.195 +  a->delayed()->nop();
   1.196 +  nc = nativeCall_at( cb.code_begin() );
   1.197 +  nc->print();
   1.198 +
   1.199 +  nc = nativeCall_overwriting_at( nc->next_instruction_address() );
   1.200 +  for (idx = 0; idx < ARRAY_SIZE(offsets); idx++) {
   1.201 +    nc->set_destination( cb.code_begin() + offsets[idx] );
   1.202 +    assert(nc->destination() == (cb.code_begin() + offsets[idx]), "check unit test");
   1.203 +    nc->print();
   1.204 +  }
   1.205 +
   1.206 +  nc = nativeCall_before( cb.code_begin() + 8 );
   1.207 +  nc->print();
   1.208 +
   1.209 +  VM_Version::revert();
   1.210 +#endif
   1.211 +}
   1.212 +// End code for unit testing implementation of NativeCall class
   1.213 +
   1.214 +//-------------------------------------------------------------------
   1.215 +
   1.216 +#ifdef _LP64
   1.217 +
   1.218 +void NativeFarCall::set_destination(address dest) {
   1.219 +  // Address materialized in the instruction stream, so nothing to do.
   1.220 +  return;
   1.221 +#if 0 // What we'd do if we really did want to change the destination
   1.222 +  if (destination() == dest) {
   1.223 +    return;
   1.224 +  }
   1.225 +  ResourceMark rm;
   1.226 +  CodeBuffer buf(addr_at(0), instruction_size + 1);
   1.227 +  MacroAssembler* _masm = new MacroAssembler(&buf);
   1.228 +  // Generate the new sequence
   1.229 +  Address(O7, dest);
   1.230 +  _masm->jumpl_to(dest, O7);
   1.231 +  ICache::invalidate_range(addr_at(0), instruction_size );
   1.232 +#endif
   1.233 +}
   1.234 +
   1.235 +void NativeFarCall::verify() {
   1.236 +  // make sure code pattern is actually a jumpl_to instruction
   1.237 +  assert((int)instruction_size == (int)NativeJump::instruction_size, "same as jump_to");
   1.238 +  assert((int)jmpl_offset == (int)NativeMovConstReg::add_offset, "sethi size ok");
   1.239 +  nativeJump_at(addr_at(0))->verify();
   1.240 +}
   1.241 +
   1.242 +bool NativeFarCall::is_call_at(address instr) {
   1.243 +  return nativeInstruction_at(instr)->is_sethi();
   1.244 +}
   1.245 +
   1.246 +void NativeFarCall::print() {
   1.247 +  tty->print_cr(INTPTR_FORMAT ": call " INTPTR_FORMAT, instruction_address(), destination());
   1.248 +}
   1.249 +
   1.250 +bool NativeFarCall::destination_is_compiled_verified_entry_point() {
   1.251 +  nmethod* callee = CodeCache::find_nmethod(destination());
   1.252 +  if (callee == NULL) {
   1.253 +    return false;
   1.254 +  } else {
   1.255 +    return destination() == callee->verified_entry_point();
   1.256 +  }
   1.257 +}
   1.258 +
   1.259 +// MT-safe patching of a far call.
   1.260 +void NativeFarCall::replace_mt_safe(address instr_addr, address code_buffer) {
   1.261 +  Unimplemented();
   1.262 +}
   1.263 +
   1.264 +// Code for unit testing implementation of NativeFarCall class
   1.265 +void NativeFarCall::test() {
   1.266 +  Unimplemented();
   1.267 +}
   1.268 +// End code for unit testing implementation of NativeFarCall class
   1.269 +
   1.270 +#endif // _LP64
   1.271 +
   1.272 +//-------------------------------------------------------------------
   1.273 +
   1.274 +
   1.275 +void NativeMovConstReg::verify() {
   1.276 +  NativeInstruction::verify();
   1.277 +  // make sure code pattern is actually a "set_oop" synthetic instruction
   1.278 +  // see MacroAssembler::set_oop()
   1.279 +  int i0 = long_at(sethi_offset);
   1.280 +  int i1 = long_at(add_offset);
   1.281 +
   1.282 +  // verify the pattern "sethi %hi22(imm), reg ;  add reg, %lo10(imm), reg"
   1.283 +  Register rd = inv_rd(i0);
   1.284 +#ifndef _LP64
   1.285 +  if (!(is_op2(i0, Assembler::sethi_op2) && rd != G0 &&
   1.286 +        is_op3(i1, Assembler::add_op3, Assembler::arith_op) &&
   1.287 +        inv_immed(i1) && (unsigned)get_simm13(i1) < (1 << 10) &&
   1.288 +        rd == inv_rs1(i1) && rd == inv_rd(i1))) {
   1.289 +    fatal("not a set_oop");
   1.290 +  }
   1.291 +#else
   1.292 +  if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) {
   1.293 +    fatal("not a set_oop");
   1.294 +  }
   1.295 +#endif
   1.296 +}
   1.297 +
   1.298 +
   1.299 +void NativeMovConstReg::print() {
   1.300 +  tty->print_cr(INTPTR_FORMAT ": mov reg, " INTPTR_FORMAT, instruction_address(), data());
   1.301 +}
   1.302 +
   1.303 +
   1.304 +#ifdef _LP64
   1.305 +intptr_t NativeMovConstReg::data() const {
   1.306 +  return data64(addr_at(sethi_offset), long_at(add_offset));
   1.307 +}
   1.308 +#else
   1.309 +intptr_t NativeMovConstReg::data() const {
   1.310 +  return data32(long_at(sethi_offset), long_at(add_offset));
   1.311 +}
   1.312 +#endif
   1.313 +
   1.314 +
   1.315 +void NativeMovConstReg::set_data(intptr_t x) {
   1.316 +#ifdef _LP64
   1.317 +  set_data64_sethi(addr_at(sethi_offset), x);
   1.318 +#else
   1.319 +  set_long_at(sethi_offset, set_data32_sethi(  long_at(sethi_offset), x));
   1.320 +#endif
   1.321 +  set_long_at(add_offset,   set_data32_simm13( long_at(add_offset),   x));
   1.322 +
   1.323 +  // also store the value into an oop_Relocation cell, if any
   1.324 +  CodeBlob* nm = CodeCache::find_blob(instruction_address());
   1.325 +  if (nm != NULL) {
   1.326 +    RelocIterator iter(nm, instruction_address(), next_instruction_address());
   1.327 +    oop* oop_addr = NULL;
   1.328 +    while (iter.next()) {
   1.329 +      if (iter.type() == relocInfo::oop_type) {
   1.330 +        oop_Relocation *r = iter.oop_reloc();
   1.331 +        if (oop_addr == NULL) {
   1.332 +          oop_addr = r->oop_addr();
   1.333 +          *oop_addr = (oop)x;
   1.334 +        } else {
   1.335 +          assert(oop_addr == r->oop_addr(), "must be only one set-oop here");
   1.336 +        }
   1.337 +      }
   1.338 +    }
   1.339 +  }
   1.340 +}
   1.341 +
   1.342 +
   1.343 +// Code for unit testing implementation of NativeMovConstReg class
   1.344 +void NativeMovConstReg::test() {
   1.345 +#ifdef ASSERT
   1.346 +  ResourceMark rm;
   1.347 +  CodeBuffer cb("test", 100, 100);
   1.348 +  MacroAssembler* a = new MacroAssembler(&cb);
   1.349 +  NativeMovConstReg* nm;
   1.350 +  uint idx;
   1.351 +  int offsets[] = {
   1.352 +    0x0,
   1.353 +    0x7fffffff,
   1.354 +    0x80000000,
   1.355 +    0xffffffff,
   1.356 +    0x20,
   1.357 +    4096,
   1.358 +    4097,
   1.359 +  };
   1.360 +
   1.361 +  VM_Version::allow_all();
   1.362 +
   1.363 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none);
   1.364 +  a->add(I3, low10(0xaaaabbbb), I3);
   1.365 +  a->sethi(0xccccdddd, O2, true, RelocationHolder::none);
   1.366 +  a->add(O2, low10(0xccccdddd), O2);
   1.367 +
   1.368 +  nm = nativeMovConstReg_at( cb.code_begin() );
   1.369 +  nm->print();
   1.370 +
   1.371 +  nm = nativeMovConstReg_at( nm->next_instruction_address() );
   1.372 +  for (idx = 0; idx < ARRAY_SIZE(offsets); idx++) {
   1.373 +    nm->set_data( offsets[idx] );
   1.374 +    assert(nm->data() == offsets[idx], "check unit test");
   1.375 +  }
   1.376 +  nm->print();
   1.377 +
   1.378 +  VM_Version::revert();
   1.379 +#endif
   1.380 +}
   1.381 +// End code for unit testing implementation of NativeMovConstReg class
   1.382 +
   1.383 +//-------------------------------------------------------------------
   1.384 +
   1.385 +void NativeMovConstRegPatching::verify() {
   1.386 +  NativeInstruction::verify();
   1.387 +  // Make sure code pattern is sethi/nop/add.
   1.388 +  int i0 = long_at(sethi_offset);
   1.389 +  int i1 = long_at(nop_offset);
   1.390 +  int i2 = long_at(add_offset);
   1.391 +  assert((int)nop_offset == (int)NativeMovConstReg::add_offset, "sethi size ok");
   1.392 +
   1.393 +  // Verify the pattern "sethi %hi22(imm), reg; nop; add reg, %lo10(imm), reg"
   1.394 +  // The casual reader should note that on Sparc a nop is a special case if sethi
   1.395 +  // in which the destination register is %g0.
   1.396 +  Register rd0 = inv_rd(i0);
   1.397 +  Register rd1 = inv_rd(i1);
   1.398 +  if (!(is_op2(i0, Assembler::sethi_op2) && rd0 != G0 &&
   1.399 +        is_op2(i1, Assembler::sethi_op2) && rd1 == G0 &&        // nop is a special case of sethi
   1.400 +        is_op3(i2, Assembler::add_op3, Assembler::arith_op) &&
   1.401 +        inv_immed(i2) && (unsigned)get_simm13(i2) < (1 << 10) &&
   1.402 +        rd0 == inv_rs1(i2) && rd0 == inv_rd(i2))) {
   1.403 +    fatal("not a set_oop");
   1.404 +  }
   1.405 +}
   1.406 +
   1.407 +
   1.408 +void NativeMovConstRegPatching::print() {
   1.409 +  tty->print_cr(INTPTR_FORMAT ": mov reg, " INTPTR_FORMAT, instruction_address(), data());
   1.410 +}
   1.411 +
   1.412 +
   1.413 +int NativeMovConstRegPatching::data() const {
   1.414 +#ifdef _LP64
   1.415 +  return data64(addr_at(sethi_offset), long_at(add_offset));
   1.416 +#else
   1.417 +  return data32(long_at(sethi_offset), long_at(add_offset));
   1.418 +#endif
   1.419 +}
   1.420 +
   1.421 +
   1.422 +void NativeMovConstRegPatching::set_data(int x) {
   1.423 +#ifdef _LP64
   1.424 +  set_data64_sethi(addr_at(sethi_offset), x);
   1.425 +#else
   1.426 +  set_long_at(sethi_offset, set_data32_sethi(long_at(sethi_offset), x));
   1.427 +#endif
   1.428 +  set_long_at(add_offset, set_data32_simm13(long_at(add_offset), x));
   1.429 +
   1.430 +  // also store the value into an oop_Relocation cell, if any
   1.431 +  CodeBlob* nm = CodeCache::find_blob(instruction_address());
   1.432 +  if (nm != NULL) {
   1.433 +    RelocIterator iter(nm, instruction_address(), next_instruction_address());
   1.434 +    oop* oop_addr = NULL;
   1.435 +    while (iter.next()) {
   1.436 +      if (iter.type() == relocInfo::oop_type) {
   1.437 +        oop_Relocation *r = iter.oop_reloc();
   1.438 +        if (oop_addr == NULL) {
   1.439 +          oop_addr = r->oop_addr();
   1.440 +          *oop_addr = (oop)x;
   1.441 +        } else {
   1.442 +          assert(oop_addr == r->oop_addr(), "must be only one set-oop here");
   1.443 +        }
   1.444 +      }
   1.445 +    }
   1.446 +  }
   1.447 +}
   1.448 +
   1.449 +
   1.450 +// Code for unit testing implementation of NativeMovConstRegPatching class
   1.451 +void NativeMovConstRegPatching::test() {
   1.452 +#ifdef ASSERT
   1.453 +  ResourceMark rm;
   1.454 +  CodeBuffer cb("test", 100, 100);
   1.455 +  MacroAssembler* a = new MacroAssembler(&cb);
   1.456 +  NativeMovConstRegPatching* nm;
   1.457 +  uint idx;
   1.458 +  int offsets[] = {
   1.459 +    0x0,
   1.460 +    0x7fffffff,
   1.461 +    0x80000000,
   1.462 +    0xffffffff,
   1.463 +    0x20,
   1.464 +    4096,
   1.465 +    4097,
   1.466 +  };
   1.467 +
   1.468 +  VM_Version::allow_all();
   1.469 +
   1.470 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none);
   1.471 +  a->nop();
   1.472 +  a->add(I3, low10(0xaaaabbbb), I3);
   1.473 +  a->sethi(0xccccdddd, O2, true, RelocationHolder::none);
   1.474 +  a->nop();
   1.475 +  a->add(O2, low10(0xccccdddd), O2);
   1.476 +
   1.477 +  nm = nativeMovConstRegPatching_at( cb.code_begin() );
   1.478 +  nm->print();
   1.479 +
   1.480 +  nm = nativeMovConstRegPatching_at( nm->next_instruction_address() );
   1.481 +  for (idx = 0; idx < ARRAY_SIZE(offsets); idx++) {
   1.482 +    nm->set_data( offsets[idx] );
   1.483 +    assert(nm->data() == offsets[idx], "check unit test");
   1.484 +  }
   1.485 +  nm->print();
   1.486 +
   1.487 +  VM_Version::revert();
   1.488 +#endif // ASSERT
   1.489 +}
   1.490 +// End code for unit testing implementation of NativeMovConstRegPatching class
   1.491 +
   1.492 +
   1.493 +//-------------------------------------------------------------------
   1.494 +
   1.495 +
   1.496 +void NativeMovRegMem::copy_instruction_to(address new_instruction_address) {
   1.497 +  Untested("copy_instruction_to");
   1.498 +  int instruction_size = next_instruction_address() - instruction_address();
   1.499 +  for (int i = 0; i < instruction_size; i += BytesPerInstWord) {
   1.500 +    *(int*)(new_instruction_address + i) = *(int*)(address(this) + i);
   1.501 +  }
   1.502 +}
   1.503 +
   1.504 +
   1.505 +void NativeMovRegMem::verify() {
   1.506 +  NativeInstruction::verify();
   1.507 +  // make sure code pattern is actually a "ld" or "st" of some sort.
   1.508 +  int i0 = long_at(0);
   1.509 +  int op3 = inv_op3(i0);
   1.510 +
   1.511 +  assert((int)add_offset == NativeMovConstReg::add_offset, "sethi size ok");
   1.512 +
   1.513 +  if (!(is_op(i0, Assembler::ldst_op) &&
   1.514 +        inv_immed(i0) &&
   1.515 +        0 != (op3 < op3_ldst_int_limit
   1.516 +         ? (1 <<  op3                      ) & (op3_mask_ld  | op3_mask_st)
   1.517 +         : (1 << (op3 - op3_ldst_int_limit)) & (op3_mask_ldf | op3_mask_stf))))
   1.518 +  {
   1.519 +    int i1 = long_at(ldst_offset);
   1.520 +    Register rd = inv_rd(i0);
   1.521 +
   1.522 +    op3 = inv_op3(i1);
   1.523 +    if (!is_op(i1, Assembler::ldst_op) && rd == inv_rs2(i1) &&
   1.524 +         0 != (op3 < op3_ldst_int_limit
   1.525 +              ? (1 <<  op3                      ) & (op3_mask_ld  | op3_mask_st)
   1.526 +               : (1 << (op3 - op3_ldst_int_limit)) & (op3_mask_ldf | op3_mask_stf))) {
   1.527 +      fatal("not a ld* or st* op");
   1.528 +    }
   1.529 +  }
   1.530 +}
   1.531 +
   1.532 +
   1.533 +void NativeMovRegMem::print() {
   1.534 +  if (is_immediate()) {
   1.535 +    tty->print_cr(INTPTR_FORMAT ": mov reg, [reg + %x]", instruction_address(), offset());
   1.536 +  } else {
   1.537 +    tty->print_cr(INTPTR_FORMAT ": mov reg, [reg + reg]", instruction_address());
   1.538 +  }
   1.539 +}
   1.540 +
   1.541 +
   1.542 +// Code for unit testing implementation of NativeMovRegMem class
   1.543 +void NativeMovRegMem::test() {
   1.544 +#ifdef ASSERT
   1.545 +  ResourceMark rm;
   1.546 +  CodeBuffer cb("test", 1000, 1000);
   1.547 +  MacroAssembler* a = new MacroAssembler(&cb);
   1.548 +  NativeMovRegMem* nm;
   1.549 +  uint idx = 0;
   1.550 +  uint idx1;
   1.551 +  int offsets[] = {
   1.552 +    0x0,
   1.553 +    0xffffffff,
   1.554 +    0x7fffffff,
   1.555 +    0x80000000,
   1.556 +    4096,
   1.557 +    4097,
   1.558 +    0x20,
   1.559 +    0x4000,
   1.560 +  };
   1.561 +
   1.562 +  VM_Version::allow_all();
   1.563 +
   1.564 +  a->ldsw( G5, low10(0xffffffff), G4 ); idx++;
   1.565 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.566 +  a->ldsw( G5, I3, G4 ); idx++;
   1.567 +  a->ldsb( G5, low10(0xffffffff), G4 ); idx++;
   1.568 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.569 +  a->ldsb( G5, I3, G4 ); idx++;
   1.570 +  a->ldsh( G5, low10(0xffffffff), G4 ); idx++;
   1.571 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.572 +  a->ldsh( G5, I3, G4 ); idx++;
   1.573 +  a->lduw( G5, low10(0xffffffff), G4 ); idx++;
   1.574 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.575 +  a->lduw( G5, I3, G4 ); idx++;
   1.576 +  a->ldub( G5, low10(0xffffffff), G4 ); idx++;
   1.577 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.578 +  a->ldub( G5, I3, G4 ); idx++;
   1.579 +  a->lduh( G5, low10(0xffffffff), G4 ); idx++;
   1.580 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.581 +  a->lduh( G5, I3, G4 ); idx++;
   1.582 +  a->ldx( G5, low10(0xffffffff), G4 ); idx++;
   1.583 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.584 +  a->ldx( G5, I3, G4 ); idx++;
   1.585 +  a->ldd( G5, low10(0xffffffff), G4 ); idx++;
   1.586 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.587 +  a->ldd( G5, I3, G4 ); idx++;
   1.588 +  a->ldf( FloatRegisterImpl::D, O2, -1, F14 ); idx++;
   1.589 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.590 +  a->ldf( FloatRegisterImpl::S, O0, I3, F15 ); idx++;
   1.591 +
   1.592 +  a->stw( G5, G4, low10(0xffffffff) ); idx++;
   1.593 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.594 +  a->stw( G5, G4, I3 ); idx++;
   1.595 +  a->stb( G5, G4, low10(0xffffffff) ); idx++;
   1.596 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.597 +  a->stb( G5, G4, I3 ); idx++;
   1.598 +  a->sth( G5, G4, low10(0xffffffff) ); idx++;
   1.599 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.600 +  a->sth( G5, G4, I3 ); idx++;
   1.601 +  a->stx( G5, G4, low10(0xffffffff) ); idx++;
   1.602 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.603 +  a->stx( G5, G4, I3 ); idx++;
   1.604 +  a->std( G5, G4, low10(0xffffffff) ); idx++;
   1.605 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.606 +  a->std( G5, G4, I3 ); idx++;
   1.607 +  a->stf( FloatRegisterImpl::S, F18, O2, -1 ); idx++;
   1.608 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
   1.609 +  a->stf( FloatRegisterImpl::S, F15, O0, I3 ); idx++;
   1.610 +
   1.611 +  nm = nativeMovRegMem_at( cb.code_begin() );
   1.612 +  nm->print();
   1.613 +  nm->set_offset( low10(0) );
   1.614 +  nm->print();
   1.615 +  nm->add_offset_in_bytes( low10(0xbb) * wordSize );
   1.616 +  nm->print();
   1.617 +
   1.618 +  while (--idx) {
   1.619 +    nm = nativeMovRegMem_at( nm->next_instruction_address() );
   1.620 +    nm->print();
   1.621 +    for (idx1 = 0; idx1 < ARRAY_SIZE(offsets); idx1++) {
   1.622 +      nm->set_offset( nm->is_immediate() ? low10(offsets[idx1]) : offsets[idx1] );
   1.623 +      assert(nm->offset() == (nm->is_immediate() ? low10(offsets[idx1]) : offsets[idx1]),
   1.624 +             "check unit test");
   1.625 +      nm->print();
   1.626 +    }
   1.627 +    nm->add_offset_in_bytes( low10(0xbb) * wordSize );
   1.628 +    nm->print();
   1.629 +  }
   1.630 +
   1.631 +  VM_Version::revert();
   1.632 +#endif // ASSERT
   1.633 +}
   1.634 +
   1.635 +// End code for unit testing implementation of NativeMovRegMem class
   1.636 +
   1.637 +//--------------------------------------------------------------------------------
   1.638 +
   1.639 +
   1.640 +void NativeMovRegMemPatching::copy_instruction_to(address new_instruction_address) {
   1.641 +  Untested("copy_instruction_to");
   1.642 +  int instruction_size = next_instruction_address() - instruction_address();
   1.643 +  for (int i = 0; i < instruction_size; i += wordSize) {
   1.644 +    *(long*)(new_instruction_address + i) = *(long*)(address(this) + i);
   1.645 +  }
   1.646 +}
   1.647 +
   1.648 +
   1.649 +void NativeMovRegMemPatching::verify() {
   1.650 +  NativeInstruction::verify();
   1.651 +  // make sure code pattern is actually a "ld" or "st" of some sort.
   1.652 +  int i0 = long_at(0);
   1.653 +  int op3 = inv_op3(i0);
   1.654 +
   1.655 +  assert((int)nop_offset == (int)NativeMovConstReg::add_offset, "sethi size ok");
   1.656 +
   1.657 +  if (!(is_op(i0, Assembler::ldst_op) &&
   1.658 +        inv_immed(i0) &&
   1.659 +        0 != (op3 < op3_ldst_int_limit
   1.660 +         ? (1 <<  op3                      ) & (op3_mask_ld  | op3_mask_st)
   1.661 +         : (1 << (op3 - op3_ldst_int_limit)) & (op3_mask_ldf | op3_mask_stf)))) {
   1.662 +    int i1 = long_at(ldst_offset);
   1.663 +    Register rd = inv_rd(i0);
   1.664 +
   1.665 +    op3 = inv_op3(i1);
   1.666 +    if (!is_op(i1, Assembler::ldst_op) && rd == inv_rs2(i1) &&
   1.667 +         0 != (op3 < op3_ldst_int_limit
   1.668 +              ? (1 <<  op3                      ) & (op3_mask_ld  | op3_mask_st)
   1.669 +              : (1 << (op3 - op3_ldst_int_limit)) & (op3_mask_ldf | op3_mask_stf))) {
   1.670 +      fatal("not a ld* or st* op");
   1.671 +    }
   1.672 +  }
   1.673 +}
   1.674 +
   1.675 +
   1.676 +void NativeMovRegMemPatching::print() {
   1.677 +  if (is_immediate()) {
   1.678 +    tty->print_cr(INTPTR_FORMAT ": mov reg, [reg + %x]", instruction_address(), offset());
   1.679 +  } else {
   1.680 +    tty->print_cr(INTPTR_FORMAT ": mov reg, [reg + reg]", instruction_address());
   1.681 +  }
   1.682 +}
   1.683 +
   1.684 +
   1.685 +// Code for unit testing implementation of NativeMovRegMemPatching class
   1.686 +void NativeMovRegMemPatching::test() {
   1.687 +#ifdef ASSERT
   1.688 +  ResourceMark rm;
   1.689 +  CodeBuffer cb("test", 1000, 1000);
   1.690 +  MacroAssembler* a = new MacroAssembler(&cb);
   1.691 +  NativeMovRegMemPatching* nm;
   1.692 +  uint idx = 0;
   1.693 +  uint idx1;
   1.694 +  int offsets[] = {
   1.695 +    0x0,
   1.696 +    0xffffffff,
   1.697 +    0x7fffffff,
   1.698 +    0x80000000,
   1.699 +    4096,
   1.700 +    4097,
   1.701 +    0x20,
   1.702 +    0x4000,
   1.703 +  };
   1.704 +
   1.705 +  VM_Version::allow_all();
   1.706 +
   1.707 +  a->ldsw( G5, low10(0xffffffff), G4 ); idx++;
   1.708 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.709 +  a->ldsw( G5, I3, G4 ); idx++;
   1.710 +  a->ldsb( G5, low10(0xffffffff), G4 ); idx++;
   1.711 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.712 +  a->ldsb( G5, I3, G4 ); idx++;
   1.713 +  a->ldsh( G5, low10(0xffffffff), G4 ); idx++;
   1.714 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.715 +  a->ldsh( G5, I3, G4 ); idx++;
   1.716 +  a->lduw( G5, low10(0xffffffff), G4 ); idx++;
   1.717 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.718 +  a->lduw( G5, I3, G4 ); idx++;
   1.719 +  a->ldub( G5, low10(0xffffffff), G4 ); idx++;
   1.720 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.721 +  a->ldub( G5, I3, G4 ); idx++;
   1.722 +  a->lduh( G5, low10(0xffffffff), G4 ); idx++;
   1.723 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.724 +  a->lduh( G5, I3, G4 ); idx++;
   1.725 +  a->ldx( G5, low10(0xffffffff), G4 ); idx++;
   1.726 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.727 +  a->ldx( G5, I3, G4 ); idx++;
   1.728 +  a->ldd( G5, low10(0xffffffff), G4 ); idx++;
   1.729 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.730 +  a->ldd( G5, I3, G4 ); idx++;
   1.731 +  a->ldf( FloatRegisterImpl::D, O2, -1, F14 ); idx++;
   1.732 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.733 +  a->ldf( FloatRegisterImpl::S, O0, I3, F15 ); idx++;
   1.734 +
   1.735 +  a->stw( G5, G4, low10(0xffffffff) ); idx++;
   1.736 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.737 +  a->stw( G5, G4, I3 ); idx++;
   1.738 +  a->stb( G5, G4, low10(0xffffffff) ); idx++;
   1.739 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.740 +  a->stb( G5, G4, I3 ); idx++;
   1.741 +  a->sth( G5, G4, low10(0xffffffff) ); idx++;
   1.742 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.743 +  a->sth( G5, G4, I3 ); idx++;
   1.744 +  a->stx( G5, G4, low10(0xffffffff) ); idx++;
   1.745 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.746 +  a->stx( G5, G4, I3 ); idx++;
   1.747 +  a->std( G5, G4, low10(0xffffffff) ); idx++;
   1.748 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.749 +  a->std( G5, G4, I3 ); idx++;
   1.750 +  a->stf( FloatRegisterImpl::S, F18, O2, -1 ); idx++;
   1.751 +  a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
   1.752 +  a->stf( FloatRegisterImpl::S, F15, O0, I3 ); idx++;
   1.753 +
   1.754 +  nm = nativeMovRegMemPatching_at( cb.code_begin() );
   1.755 +  nm->print();
   1.756 +  nm->set_offset( low10(0) );
   1.757 +  nm->print();
   1.758 +  nm->add_offset_in_bytes( low10(0xbb) * wordSize );
   1.759 +  nm->print();
   1.760 +
   1.761 +  while (--idx) {
   1.762 +    nm = nativeMovRegMemPatching_at( nm->next_instruction_address() );
   1.763 +    nm->print();
   1.764 +    for (idx1 = 0; idx1 < ARRAY_SIZE(offsets); idx1++) {
   1.765 +      nm->set_offset( nm->is_immediate() ? low10(offsets[idx1]) : offsets[idx1] );
   1.766 +      assert(nm->offset() == (nm->is_immediate() ? low10(offsets[idx1]) : offsets[idx1]),
   1.767 +             "check unit test");
   1.768 +      nm->print();
   1.769 +    }
   1.770 +    nm->add_offset_in_bytes( low10(0xbb) * wordSize );
   1.771 +    nm->print();
   1.772 +  }
   1.773 +
   1.774 +  VM_Version::revert();
   1.775 +#endif // ASSERT
   1.776 +}
   1.777 +// End code for unit testing implementation of NativeMovRegMemPatching class
   1.778 +
   1.779 +
   1.780 +//--------------------------------------------------------------------------------
   1.781 +
   1.782 +
   1.783 +void NativeJump::verify() {
   1.784 +  NativeInstruction::verify();
   1.785 +  int i0 = long_at(sethi_offset);
   1.786 +  int i1 = long_at(jmpl_offset);
   1.787 +  assert((int)jmpl_offset == (int)NativeMovConstReg::add_offset, "sethi size ok");
   1.788 +  // verify the pattern "sethi %hi22(imm), treg ;  jmpl treg, %lo10(imm), lreg"
   1.789 +  Register rd = inv_rd(i0);
   1.790 +#ifndef _LP64
   1.791 +  if (!(is_op2(i0, Assembler::sethi_op2) && rd != G0 &&
   1.792 +        (is_op3(i1, Assembler::jmpl_op3, Assembler::arith_op) ||
   1.793 +        (TraceJumps && is_op3(i1, Assembler::add_op3, Assembler::arith_op))) &&
   1.794 +        inv_immed(i1) && (unsigned)get_simm13(i1) < (1 << 10) &&
   1.795 +        rd == inv_rs1(i1))) {
   1.796 +    fatal("not a jump_to instruction");
   1.797 +  }
   1.798 +#else
   1.799 +  // In LP64, the jump instruction location varies for non relocatable
   1.800 +  // jumps, for example is could be sethi, xor, jmp instead of the
   1.801 +  // 7 instructions for sethi.  So let's check sethi only.
   1.802 +  if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) {
   1.803 +    fatal("not a jump_to instruction");
   1.804 +  }
   1.805 +#endif
   1.806 +}
   1.807 +
   1.808 +
   1.809 +void NativeJump::print() {
   1.810 +  tty->print_cr(INTPTR_FORMAT ": jmpl reg, " INTPTR_FORMAT, instruction_address(), jump_destination());
   1.811 +}
   1.812 +
   1.813 +
   1.814 +// Code for unit testing implementation of NativeJump class
   1.815 +void NativeJump::test() {
   1.816 +#ifdef ASSERT
   1.817 +  ResourceMark rm;
   1.818 +  CodeBuffer cb("test", 100, 100);
   1.819 +  MacroAssembler* a = new MacroAssembler(&cb);
   1.820 +  NativeJump* nj;
   1.821 +  uint idx;
   1.822 +  int offsets[] = {
   1.823 +    0x0,
   1.824 +    0xffffffff,
   1.825 +    0x7fffffff,
   1.826 +    0x80000000,
   1.827 +    4096,
   1.828 +    4097,
   1.829 +    0x20,
   1.830 +    0x4000,
   1.831 +  };
   1.832 +
   1.833 +  VM_Version::allow_all();
   1.834 +
   1.835 +  a->sethi(0x7fffbbbb, I3, true, RelocationHolder::none);
   1.836 +  a->jmpl(I3, low10(0x7fffbbbb), G0, RelocationHolder::none);
   1.837 +  a->delayed()->nop();
   1.838 +  a->sethi(0x7fffbbbb, I3, true, RelocationHolder::none);
   1.839 +  a->jmpl(I3, low10(0x7fffbbbb), L3, RelocationHolder::none);
   1.840 +  a->delayed()->nop();
   1.841 +
   1.842 +  nj = nativeJump_at( cb.code_begin() );
   1.843 +  nj->print();
   1.844 +
   1.845 +  nj = nativeJump_at( nj->next_instruction_address() );
   1.846 +  for (idx = 0; idx < ARRAY_SIZE(offsets); idx++) {
   1.847 +    nj->set_jump_destination( nj->instruction_address() + offsets[idx] );
   1.848 +    assert(nj->jump_destination() == (nj->instruction_address() + offsets[idx]), "check unit test");
   1.849 +    nj->print();
   1.850 +  }
   1.851 +
   1.852 +  VM_Version::revert();
   1.853 +#endif // ASSERT
   1.854 +}
   1.855 +// End code for unit testing implementation of NativeJump class
   1.856 +
   1.857 +
   1.858 +void NativeJump::insert(address code_pos, address entry) {
   1.859 +  Unimplemented();
   1.860 +}
   1.861 +
   1.862 +// MT safe inserting of a jump over an unknown instruction sequence (used by nmethod::makeZombie)
   1.863 +// The problem: jump_to <dest> is a 3-word instruction (including its delay slot).
   1.864 +// Atomic write can be only with 1 word.
   1.865 +void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
   1.866 +  // Here's one way to do it:  Pre-allocate a three-word jump sequence somewhere
   1.867 +  // in the header of the nmethod, within a short branch's span of the patch point.
   1.868 +  // Set up the jump sequence using NativeJump::insert, and then use an annulled
   1.869 +  // unconditional branch at the target site (an atomic 1-word update).
   1.870 +  // Limitations:  You can only patch nmethods, with any given nmethod patched at
   1.871 +  // most once, and the patch must be in the nmethod's header.
   1.872 +  // It's messy, but you can ask the CodeCache for the nmethod containing the
   1.873 +  // target address.
   1.874 +
   1.875 +  // %%%%% For now, do something MT-stupid:
   1.876 +  ResourceMark rm;
   1.877 +  int code_size = 1 * BytesPerInstWord;
   1.878 +  CodeBuffer cb(verified_entry, code_size + 1);
   1.879 +  MacroAssembler* a = new MacroAssembler(&cb);
   1.880 +  if (VM_Version::v9_instructions_work()) {
   1.881 +    a->ldsw(G0, 0, O7); // "ld" must agree with code in the signal handler
   1.882 +  } else {
   1.883 +    a->lduw(G0, 0, O7); // "ld" must agree with code in the signal handler
   1.884 +  }
   1.885 +  ICache::invalidate_range(verified_entry, code_size);
   1.886 +}
   1.887 +
   1.888 +
   1.889 +void NativeIllegalInstruction::insert(address code_pos) {
   1.890 +  NativeIllegalInstruction* nii = (NativeIllegalInstruction*) nativeInstruction_at(code_pos);
   1.891 +  nii->set_long_at(0, illegal_instruction());
   1.892 +}
   1.893 +
   1.894 +static int illegal_instruction_bits = 0;
   1.895 +
   1.896 +int NativeInstruction::illegal_instruction() {
   1.897 +  if (illegal_instruction_bits == 0) {
   1.898 +    ResourceMark rm;
   1.899 +    char buf[40];
   1.900 +    CodeBuffer cbuf((address)&buf[0], 20);
   1.901 +    MacroAssembler* a = new MacroAssembler(&cbuf);
   1.902 +    address ia = a->pc();
   1.903 +    a->trap(ST_RESERVED_FOR_USER_0 + 1);
   1.904 +    int bits = *(int*)ia;
   1.905 +    assert(is_op3(bits, Assembler::trap_op3, Assembler::arith_op), "bad instruction");
   1.906 +    illegal_instruction_bits = bits;
   1.907 +    assert(illegal_instruction_bits != 0, "oops");
   1.908 +  }
   1.909 +  return illegal_instruction_bits;
   1.910 +}
   1.911 +
   1.912 +static int ic_miss_trap_bits = 0;
   1.913 +
   1.914 +bool NativeInstruction::is_ic_miss_trap() {
   1.915 +  if (ic_miss_trap_bits == 0) {
   1.916 +    ResourceMark rm;
   1.917 +    char buf[40];
   1.918 +    CodeBuffer cbuf((address)&buf[0], 20);
   1.919 +    MacroAssembler* a = new MacroAssembler(&cbuf);
   1.920 +    address ia = a->pc();
   1.921 +    a->trap(Assembler::notEqual, Assembler::ptr_cc, G0, ST_RESERVED_FOR_USER_0 + 2);
   1.922 +    int bits = *(int*)ia;
   1.923 +    assert(is_op3(bits, Assembler::trap_op3, Assembler::arith_op), "bad instruction");
   1.924 +    ic_miss_trap_bits = bits;
   1.925 +    assert(ic_miss_trap_bits != 0, "oops");
   1.926 +  }
   1.927 +  return long_at(0) == ic_miss_trap_bits;
   1.928 +}
   1.929 +
   1.930 +
   1.931 +bool NativeInstruction::is_illegal() {
   1.932 +  if (illegal_instruction_bits == 0) {
   1.933 +    return false;
   1.934 +  }
   1.935 +  return long_at(0) == illegal_instruction_bits;
   1.936 +}
   1.937 +
   1.938 +
   1.939 +void NativeGeneralJump::verify() {
   1.940 +  assert(((NativeInstruction *)this)->is_jump() ||
   1.941 +         ((NativeInstruction *)this)->is_cond_jump(), "not a general jump instruction");
   1.942 +}
   1.943 +
   1.944 +
   1.945 +void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
   1.946 +  Assembler::Condition condition = Assembler::always;
   1.947 +  int x = Assembler::op2(Assembler::br_op2) | Assembler::annul(false) |
   1.948 +    Assembler::cond(condition) | Assembler::wdisp((intptr_t)entry, (intptr_t)code_pos, 22);
   1.949 +  NativeGeneralJump* ni = (NativeGeneralJump*) nativeInstruction_at(code_pos);
   1.950 +  ni->set_long_at(0, x);
   1.951 +}
   1.952 +
   1.953 +
   1.954 +// MT-safe patching of a jmp instruction (and following word).
   1.955 +// First patches the second word, and then atomicly replaces
   1.956 +// the first word with the first new instruction word.
   1.957 +// Other processors might briefly see the old first word
   1.958 +// followed by the new second word.  This is OK if the old
   1.959 +// second word is harmless, and the new second word may be
   1.960 +// harmlessly executed in the delay slot of the call.
   1.961 +void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) {
   1.962 +   assert(Patching_lock->is_locked() ||
   1.963 +         SafepointSynchronize::is_at_safepoint(), "concurrent code patching");
   1.964 +   assert (instr_addr != NULL, "illegal address for code patching");
   1.965 +   NativeGeneralJump* h_jump =  nativeGeneralJump_at (instr_addr); // checking that it is a call
   1.966 +   assert(NativeGeneralJump::instruction_size == 8, "wrong instruction size; must be 8");
   1.967 +   int i0 = ((int*)code_buffer)[0];
   1.968 +   int i1 = ((int*)code_buffer)[1];
   1.969 +   int* contention_addr = (int*) h_jump->addr_at(1*BytesPerInstWord);
   1.970 +   assert(inv_op(*contention_addr) == Assembler::arith_op ||
   1.971 +          *contention_addr == nop_instruction() || !VM_Version::v9_instructions_work(),
   1.972 +          "must not interfere with original call");
   1.973 +   // The set_long_at calls do the ICacheInvalidate so we just need to do them in reverse order
   1.974 +   h_jump->set_long_at(1*BytesPerInstWord, i1);
   1.975 +   h_jump->set_long_at(0*BytesPerInstWord, i0);
   1.976 +   // NOTE:  It is possible that another thread T will execute
   1.977 +   // only the second patched word.
   1.978 +   // In other words, since the original instruction is this
   1.979 +   //    jmp patching_stub; nop                    (NativeGeneralJump)
   1.980 +   // and the new sequence from the buffer is this:
   1.981 +   //    sethi %hi(K), %r; add %r, %lo(K), %r      (NativeMovConstReg)
   1.982 +   // what T will execute is this:
   1.983 +   //    jmp patching_stub; add %r, %lo(K), %r
   1.984 +   // thereby putting garbage into %r before calling the patching stub.
   1.985 +   // This is OK, because the patching stub ignores the value of %r.
   1.986 +
   1.987 +   // Make sure the first-patched instruction, which may co-exist
   1.988 +   // briefly with the call, will do something harmless.
   1.989 +   assert(inv_op(*contention_addr) == Assembler::arith_op ||
   1.990 +          *contention_addr == nop_instruction() || !VM_Version::v9_instructions_work(),
   1.991 +          "must not interfere with original call");
   1.992 +}

mercurial