src/hotspot/cpu/s390/nativeInst_s390.cpp
author dlong
Wed, 31 Jan 2018 16:09:29 -0800
changeset 48856 c866eaca24cb
parent 47216 71c04702a3d5
child 57583 aad50831e169
permissions -rw-r--r--
8194984: 9 Null pointer dereference defect groups related to ciMethodData::bci_to_data() Reviewed-by: kvn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     1
/*
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     2
 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     3
 * Copyright (c) 2016 SAP SE. All rights reserved.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     4
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     5
 *
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     6
 * This code is free software; you can redistribute it and/or modify it
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     7
 * under the terms of the GNU General Public License version 2 only, as
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     8
 * published by the Free Software Foundation.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     9
 *
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    10
 * This code is distributed in the hope that it will be useful, but WITHOUT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    13
 * version 2 for more details (a copy is included in the LICENSE file that
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    14
 * accompanied this code).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    15
 *
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    16
 * You should have received a copy of the GNU General Public License version
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    17
 * 2 along with this work; if not, write to the Free Software Foundation,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    18
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    19
 *
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    20
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    21
 * or visit www.oracle.com if you need additional information or have any
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    22
 * questions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    23
 *
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    24
 */
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    25
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    26
// Major contributions by JL, LS
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    27
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    28
#include "precompiled.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    29
#include "asm/macroAssembler.inline.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    30
#include "memory/resourceArea.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    31
#include "nativeInst_s390.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    32
#include "oops/oop.inline.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    33
#include "runtime/handles.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    34
#include "runtime/sharedRuntime.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    35
#include "runtime/stubRoutines.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    36
#include "utilities/ostream.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    37
#ifdef COMPILER1
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    38
#include "c1/c1_Runtime1.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    39
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    40
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    41
#define LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    42
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    43
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    44
//  N a t i v e I n s t r u c t i o n
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    45
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    46
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    47
// Define this switch to prevent identity updates.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    48
// In high-concurrency scenarios, it is beneficial to prevent
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    49
// identity updates. It has a positive effect on cache line steals.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    50
// and invalidations.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    51
// Test runs of JVM98, JVM2008, and JBB2005 show a very low frequency
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    52
// of identity updates. Detection is therefore disabled.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    53
#undef SUPPRESS_IDENTITY_UPDATE
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    54
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    55
void NativeInstruction::verify() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    56
  // Make sure code pattern is actually an instruction address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    57
  // Do not allow:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    58
  //  - NULL
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    59
  //  - any address in first page (0x0000 .. 0x0fff)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    60
  //  - odd address (will cause a "specification exception")
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    61
  address addr = addr_at(0);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    62
  if ((addr == 0) || (((unsigned long)addr & ~0x0fff) == 0) || ((intptr_t)addr & 1) != 0) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    63
    tty->print_cr(INTPTR_FORMAT ": bad instruction address", p2i(addr));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    64
    fatal("not an instruction address");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    65
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    66
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    67
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    68
// Print location and value (hex representation) of current NativeInstruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    69
void NativeInstruction::print(const char* msg) const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    70
  int len = Assembler::instr_len(addr_at(0));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    71
  if (msg == NULL) { // Output line without trailing blanks.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    72
    switch (len) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    73
      case 2: tty->print_cr(INTPTR_FORMAT "(len=%d): %4.4x",             p2i(addr_at(0)), len, halfword_at(0));                                 break;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    74
      case 4: tty->print_cr(INTPTR_FORMAT "(len=%d): %4.4x %4.4x",       p2i(addr_at(0)), len, halfword_at(0), halfword_at(2));                 break;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    75
      case 6: tty->print_cr(INTPTR_FORMAT "(len=%d): %4.4x %4.4x %4.4x", p2i(addr_at(0)), len, halfword_at(0), halfword_at(2), halfword_at(4)); break;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    76
      default: // Never reached. instr_len() always returns one of the above values. Keep the compiler happy.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    77
        ShouldNotReachHere();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    78
        break;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    79
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    80
  } else { // Output line with filler blanks to have msg aligned.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    81
    switch (len) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    82
      case 2: tty->print_cr(INTPTR_FORMAT "(len=%d): %4.4x           %s",   p2i(addr_at(0)), len, halfword_at(0), msg);                                 break;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    83
      case 4: tty->print_cr(INTPTR_FORMAT "(len=%d): %4.4x %4.4x      %s",  p2i(addr_at(0)), len, halfword_at(0), halfword_at(2), msg);                 break;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    84
      case 6: tty->print_cr(INTPTR_FORMAT "(len=%d): %4.4x %4.4x %4.4x %s", p2i(addr_at(0)), len, halfword_at(0), halfword_at(2), halfword_at(4), msg); break;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    85
      default: // Never reached. instr_len() always returns one of the above values. Keep the compiler happy.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    86
        ShouldNotReachHere();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    87
        break;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    88
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    89
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    90
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    91
void NativeInstruction::print() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    92
  print(NULL);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    93
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    94
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    95
// Hex-Dump of storage around current NativeInstruction. Also try disassembly.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    96
void NativeInstruction::dump(const unsigned int range, const char* msg) const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    97
  Assembler::dump_code_range(tty, addr_at(0), range, (msg == NULL) ? "":msg);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    98
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    99
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   100
void NativeInstruction::dump(const unsigned int range) const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   101
  dump(range, NULL);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   102
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   103
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   104
void NativeInstruction::dump() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   105
  dump(32, NULL);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   106
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   107
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   108
void NativeInstruction::set_halfword_at(int offset, short i) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   109
  address addr = addr_at(offset);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   110
#ifndef SUPPRESS_IDENTITY_UPDATE
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   111
  *(short*)addr = i;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   112
#else
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   113
  if (*(short*)addr != i) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   114
    *(short*)addr = i;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   115
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   116
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   117
  ICache::invalidate_word(addr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   118
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   119
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   120
void NativeInstruction::set_word_at(int offset, int i) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   121
  address addr = addr_at(offset);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   122
#ifndef SUPPRESS_IDENTITY_UPDATE
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   123
  *(int*)addr = i;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   124
#else
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   125
  if (*(int*)addr != i) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   126
    *(int*)addr = i;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   127
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   128
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   129
  ICache::invalidate_word(addr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   130
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   131
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   132
void NativeInstruction::set_jlong_at(int offset, jlong i) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   133
  address addr = addr_at(offset);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   134
#ifndef SUPPRESS_IDENTITY_UPDATE
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   135
  *(jlong*)addr = i;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   136
#else
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   137
  if (*(jlong*)addr != i) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   138
    *(jlong*)addr = i;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   139
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   140
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   141
  // Don't need to invalidate 2 words here, because
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   142
  // the flush instruction operates on doublewords.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   143
  ICache::invalidate_word(addr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   144
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   145
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   146
#undef  SUPPRESS_IDENTITY_UPDATE
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   147
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   148
//------------------------------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   149
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   150
int NativeInstruction::illegal_instruction() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   151
  return 0;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   152
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   153
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   154
bool NativeInstruction::is_illegal() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   155
  // An instruction with main opcode 0x00 (leftmost byte) is not a valid instruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   156
  // (and will never be) and causes a SIGILL where the pc points to the next instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   157
  // The caller of this method wants to know if such a situation exists at the current pc.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   158
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   159
  // The result of this method is unsharp with respect to the following facts:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   160
  // - Stepping backwards in the instruction stream is not possible on z/Architecture.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   161
  // - z/Architecture instructions are 2, 4, or 6 bytes in length.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   162
  // - The instruction length is coded in the leftmost two bits of the main opcode.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   163
  // - The result is exact if the caller knows by some other means that the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   164
  //   instruction is of length 2.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   165
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   166
  // If this method returns false, then the 2-byte instruction at *-2 is not a 0x00 opcode.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   167
  // If this method returns true, then the 2-byte instruction at *-2 is a 0x00 opcode.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   168
  return halfword_at(-2) == illegal_instruction();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   169
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   170
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   171
// We use an illtrap for marking a method as not_entrant or zombie.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   172
bool NativeInstruction::is_sigill_zombie_not_entrant() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   173
  if (!is_illegal()) return false; // Just a quick path.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   174
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   175
  // One-sided error of is_illegal tolerable here
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   176
  // (see implementation of is_illegal() for details).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   177
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   178
  CodeBlob* cb = CodeCache::find_blob_unsafe(addr_at(0));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   179
  if (cb == NULL || !cb->is_nmethod()) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   180
    return false;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   181
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   182
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   183
  nmethod *nm = (nmethod *)cb;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   184
  // This method is not_entrant or zombie if the illtrap instruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   185
  // is located at the verified entry point.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   186
  // BE AWARE: the current pc (this) points to the instruction after the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   187
  // "illtrap" location.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   188
  address sig_addr = ((address) this) - 2;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   189
  return nm->verified_entry_point() == sig_addr;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   190
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   191
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   192
bool NativeInstruction::is_jump() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   193
  unsigned long inst;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   194
  Assembler::get_instruction((address)this, &inst);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   195
  return MacroAssembler::is_branch_pcrelative_long(inst);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   196
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   197
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   198
//---------------------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   199
//  N a t i v e I l l e g a l I n s t r u c t i o n
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   200
//---------------------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   201
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   202
void NativeIllegalInstruction::insert(address code_pos) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   203
  NativeIllegalInstruction* nii = (NativeIllegalInstruction*) nativeInstruction_at(code_pos);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   204
  nii->set_halfword_at(0, illegal_instruction());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   205
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   206
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   207
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   208
//  N a t i v e C a l l
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   209
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   210
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   211
void NativeCall::verify() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   212
  if (NativeCall::is_call_at(addr_at(0))) return;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   213
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   214
  fatal("this is not a `NativeCall' site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   215
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   216
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   217
address NativeCall::destination() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   218
  if (MacroAssembler::is_call_far_pcrelative(instruction_address())) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   219
    address here = addr_at(MacroAssembler::nop_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   220
    return MacroAssembler::get_target_addr_pcrel(here);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   221
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   222
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   223
  return (address)((NativeMovConstReg *)this)->data();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   224
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   225
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   226
// Similar to replace_mt_safe, but just changes the destination. The
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   227
// important thing is that free-running threads are able to execute this
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   228
// call instruction at all times. Thus, the displacement field must be
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   229
// 4-byte-aligned. We enforce this on z/Architecture by inserting a nop
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   230
// instruction in front of 'brasl' when needed.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   231
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   232
// Used in the runtime linkage of calls; see class CompiledIC.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   233
void NativeCall::set_destination_mt_safe(address dest) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   234
  if (MacroAssembler::is_call_far_pcrelative(instruction_address())) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   235
    address iaddr = addr_at(MacroAssembler::nop_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   236
    // Ensure that patching is atomic hence mt safe.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   237
    assert(((long)addr_at(MacroAssembler::call_far_pcrelative_size()) & (call_far_pcrelative_displacement_alignment-1)) == 0,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   238
           "constant must be 4-byte aligned");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   239
    set_word_at(MacroAssembler::call_far_pcrelative_size() - 4, Assembler::z_pcrel_off(dest, iaddr));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   240
  } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   241
    assert(MacroAssembler::is_load_const_from_toc(instruction_address()), "unsupported instruction");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   242
    nativeMovConstReg_at(instruction_address())->set_data(((intptr_t)dest));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   243
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   244
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   245
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   246
//-----------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   247
//  N a t i v e F a r C a l l
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   248
//-----------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   249
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   250
void NativeFarCall::verify() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   251
  NativeInstruction::verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   252
  if (NativeFarCall::is_far_call_at(addr_at(0))) return;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   253
  fatal("not a NativeFarCall");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   254
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   255
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   256
address NativeFarCall::destination() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   257
  assert(MacroAssembler::is_call_far_patchable_at((address)this), "unexpected call type");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   258
  address ctable = NULL;
42556
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   259
  return MacroAssembler::get_dest_of_call_far_patchable_at((address)this, ctable);
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   260
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   261
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   262
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   263
// Handles both patterns of patchable far calls.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   264
void NativeFarCall::set_destination(address dest, int toc_offset) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   265
  address inst_addr = (address)this;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   266
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   267
  // Set new destination (implementation of call may change here).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   268
  assert(MacroAssembler::is_call_far_patchable_at(inst_addr), "unexpected call type");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   269
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   270
  if (!MacroAssembler::is_call_far_patchable_pcrelative_at(inst_addr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   271
    address ctable = CodeCache::find_blob(inst_addr)->ctable_begin();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   272
    // Need distance of TOC entry from current instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   273
    toc_offset = (ctable + toc_offset) - inst_addr;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   274
    // Call is via constant table entry.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   275
    MacroAssembler::set_dest_of_call_far_patchable_at(inst_addr, dest, toc_offset);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   276
  } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   277
    // Here, we have a pc-relative call (brasl).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   278
    // Be aware: dest may have moved in this case, so really patch the displacement,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   279
    // when necessary!
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   280
    // This while loop will also consume the nop which always preceeds a call_far_pcrelative.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   281
    // We need to revert this after the loop. Pc-relative calls are always assumed to have a leading nop.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   282
    unsigned int nop_sz    = MacroAssembler::nop_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   283
    unsigned int nop_bytes = 0;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   284
    while(MacroAssembler::is_z_nop(inst_addr+nop_bytes)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   285
      nop_bytes += nop_sz;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   286
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   287
    if (nop_bytes > 0) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   288
      inst_addr += nop_bytes - nop_sz;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   289
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   290
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   291
    assert(MacroAssembler::is_call_far_pcrelative(inst_addr), "not a pc-relative call");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   292
    address target = MacroAssembler::get_target_addr_pcrel(inst_addr + nop_sz);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   293
    if (target != dest) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   294
      NativeCall *call = nativeCall_at(inst_addr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   295
      call->set_destination_mt_safe(dest);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   296
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   297
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   298
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   299
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   300
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   301
//  N a t i v e M o v C o n s t R e g
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   302
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   303
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   304
// Do not use an assertion here. Let clients decide whether they only
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   305
// want this when assertions are enabled.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   306
void NativeMovConstReg::verify() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   307
  address   loc = addr_at(0);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   308
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   309
  // This while loop will also consume the nop which always preceeds a
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   310
  // call_far_pcrelative.  We need to revert this after the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   311
  // loop. Pc-relative calls are always assumed to have a leading nop.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   312
  unsigned int nop_sz    = MacroAssembler::nop_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   313
  unsigned int nop_bytes = 0;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   314
  while(MacroAssembler::is_z_nop(loc+nop_bytes)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   315
    nop_bytes += nop_sz;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   316
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   317
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   318
  if (nop_bytes > 0) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   319
    if (MacroAssembler::is_call_far_pcrelative(loc+nop_bytes-nop_sz)) return;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   320
    loc += nop_bytes;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   321
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   322
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   323
  if (!MacroAssembler::is_load_const_from_toc(loc)            &&    // Load const from TOC.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   324
      !MacroAssembler::is_load_const(loc)                     &&    // Load const inline.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   325
      !MacroAssembler::is_load_narrow_oop(loc)                &&    // Load narrow oop.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   326
      !MacroAssembler::is_load_narrow_klass(loc)              &&    // Load narrow Klass ptr.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   327
      !MacroAssembler::is_compare_immediate_narrow_oop(loc)   &&    // Compare immediate narrow.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   328
      !MacroAssembler::is_compare_immediate_narrow_klass(loc) &&    // Compare immediate narrow.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   329
      !MacroAssembler::is_pcrelative_instruction(loc)) {            // Just to make it run.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   330
    tty->cr();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   331
    tty->print_cr("NativeMovConstReg::verify(): verifying addr %p(0x%x), %d leading nops", loc, *(uint*)loc, nop_bytes/nop_sz);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   332
    tty->cr();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   333
    ((NativeMovConstReg*)loc)->dump(64, "NativeMovConstReg::verify()");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   334
#ifdef LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   335
    VM_Version::z_SIGSEGV();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   336
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   337
    fatal("this is not a `NativeMovConstReg' site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   338
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   339
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   340
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   341
address NativeMovConstReg::next_instruction_address(int offset) const  {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   342
  address inst_addr = addr_at(offset);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   343
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   344
  // Load address (which is a constant) pc-relative.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   345
  if (MacroAssembler::is_load_addr_pcrel(inst_addr))                  { return addr_at(offset+MacroAssembler::load_addr_pcrel_size()); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   346
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   347
  // Load constant from TOC.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   348
  if (MacroAssembler::is_load_const_from_toc(inst_addr))              { return addr_at(offset+MacroAssembler::load_const_from_toc_size()); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   349
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   350
  // Load constant inline.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   351
  if (MacroAssembler::is_load_const(inst_addr))                       { return addr_at(offset+MacroAssembler::load_const_size()); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   352
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   353
  // Load constant narrow inline.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   354
  if (MacroAssembler::is_load_narrow_oop(inst_addr))                  { return addr_at(offset+MacroAssembler::load_narrow_oop_size()); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   355
  if (MacroAssembler::is_load_narrow_klass(inst_addr))                { return addr_at(offset+MacroAssembler::load_narrow_klass_size()); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   356
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   357
  // Compare constant narrow inline.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   358
  if (MacroAssembler::is_compare_immediate_narrow_oop(inst_addr))     { return addr_at(offset+MacroAssembler::compare_immediate_narrow_oop_size()); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   359
  if (MacroAssembler::is_compare_immediate_narrow_klass(inst_addr))   { return addr_at(offset+MacroAssembler::compare_immediate_narrow_klass_size()); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   360
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   361
  if (MacroAssembler::is_call_far_patchable_pcrelative_at(inst_addr)) { return addr_at(offset+MacroAssembler::call_far_patchable_size()); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   362
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   363
  if (MacroAssembler::is_pcrelative_instruction(inst_addr))           { return addr_at(offset+Assembler::instr_len(inst_addr)); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   364
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   365
  ((NativeMovConstReg*)inst_addr)->dump(64, "NativeMovConstReg site is not recognized as such");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   366
#ifdef LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   367
  VM_Version::z_SIGSEGV();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   368
#else
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   369
  guarantee(false, "Not a NativeMovConstReg site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   370
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   371
  return NULL;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   372
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   373
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   374
intptr_t NativeMovConstReg::data() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   375
  address loc = addr_at(0);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   376
  if (MacroAssembler::is_load_const(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   377
    return MacroAssembler::get_const(loc);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   378
  } else if (MacroAssembler::is_load_narrow_oop(loc)              ||
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   379
             MacroAssembler::is_compare_immediate_narrow_oop(loc) ||
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   380
             MacroAssembler::is_load_narrow_klass(loc)            ||
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   381
             MacroAssembler::is_compare_immediate_narrow_klass(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   382
    ((NativeMovConstReg*)loc)->dump(32, "NativeMovConstReg::data(): cannot extract data from narrow ptr (oop or klass)");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   383
#ifdef LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   384
    VM_Version::z_SIGSEGV();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   385
#else
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   386
    ShouldNotReachHere();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   387
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   388
    return *(intptr_t *)NULL;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   389
  } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   390
    // Otherwise, assume data resides in TOC. Is asserted in called method.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   391
    return MacroAssembler::get_const_from_toc(loc);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   392
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   393
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   394
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   395
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   396
// Patch in a new constant.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   397
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   398
// There are situations where we have multiple (hopefully two at most)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   399
// relocations connected to one instruction. Loading an oop from CP
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   400
// using pcrelative addressing would one such example. Here we have an
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   401
// oop relocation, modifying the oop itself, and an internal word relocation,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   402
// modifying the relative address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   403
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   404
// NativeMovConstReg::set_data is then called once for each relocation. To be
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   405
// able to distinguish between the relocations, we use a rather dirty hack:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   406
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   407
// All calls that deal with an internal word relocation to fix their relative
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   408
// address are on a faked, odd instruction address. The instruction can be
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   409
// found on the next lower, even address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   410
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   411
// All other calls are "normal", i.e. on even addresses.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   412
address NativeMovConstReg::set_data_plain(intptr_t src, CodeBlob *cb) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   413
  unsigned long x = (unsigned long)src;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   414
  address loc = instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   415
  address next_address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   416
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   417
  if (MacroAssembler::is_load_addr_pcrel(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   418
    MacroAssembler::patch_target_addr_pcrel(loc, (address)src);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   419
    ICache::invalidate_range(loc, MacroAssembler::load_addr_pcrel_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   420
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   421
  } else if (MacroAssembler::is_load_const_from_toc(loc)) {  // Load constant from TOC.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   422
    MacroAssembler::set_const_in_toc(loc, src, cb);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   423
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   424
  } else if (MacroAssembler::is_load_const(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   425
    // Not mt safe, ok in methods like CodeBuffer::copy_code().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   426
    MacroAssembler::patch_const(loc, x);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   427
    ICache::invalidate_range(loc, MacroAssembler::load_const_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   428
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   429
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   430
  // cOops
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   431
  else if (MacroAssembler::is_load_narrow_oop(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   432
    MacroAssembler::patch_load_narrow_oop(loc, (oop) (void*) x);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   433
    ICache::invalidate_range(loc, MacroAssembler::load_narrow_oop_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   434
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   435
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   436
  // compressed klass ptrs
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   437
  else if (MacroAssembler::is_load_narrow_klass(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   438
    MacroAssembler::patch_load_narrow_klass(loc, (Klass*)x);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   439
    ICache::invalidate_range(loc, MacroAssembler::load_narrow_klass_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   440
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   441
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   442
  // cOops
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   443
  else if (MacroAssembler::is_compare_immediate_narrow_oop(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   444
    MacroAssembler::patch_compare_immediate_narrow_oop(loc, (oop) (void*) x);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   445
    ICache::invalidate_range(loc, MacroAssembler::compare_immediate_narrow_oop_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   446
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   447
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   448
  // compressed klass ptrs
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   449
  else if (MacroAssembler::is_compare_immediate_narrow_klass(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   450
    MacroAssembler::patch_compare_immediate_narrow_klass(loc, (Klass*)x);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   451
    ICache::invalidate_range(loc, MacroAssembler::compare_immediate_narrow_klass_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   452
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   453
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   454
  else if (MacroAssembler::is_call_far_patchable_pcrelative_at(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   455
    assert(ShortenBranches, "Wait a minute! A pc-relative call w/o ShortenBranches?");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   456
    // This NativeMovConstReg site does not need to be patched. It was
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   457
    // patched when it was converted to a call_pcrelative site
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   458
    // before. The value of the src argument is not related to the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   459
    // branch target.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   460
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   461
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   462
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   463
  else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   464
    tty->print_cr("WARNING: detected an unrecognized code pattern at loc = %p -> 0x%8.8x %8.8x",
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   465
                  loc, *((unsigned int*)loc), *((unsigned int*)(loc+4)));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   466
    next_address = next_instruction_address(); // Failure should be handled in next_instruction_address().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   467
#ifdef LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   468
    VM_Version::z_SIGSEGV();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   469
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   470
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   471
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   472
  return next_address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   473
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   474
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   475
// Divided up in set_data_plain() which patches the instruction in the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   476
// code stream and set_data() which additionally patches the oop pool
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   477
// if necessary.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   478
void NativeMovConstReg::set_data(intptr_t src) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   479
  // Also store the value into an oop_Relocation cell, if any.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   480
  CodeBlob *cb = CodeCache::find_blob(instruction_address());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   481
  address next_address = set_data_plain(src, cb);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   482
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   483
  relocInfo::update_oop_pool(instruction_address(), next_address, (address)src, cb);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   484
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   485
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   486
void NativeMovConstReg::set_narrow_oop(intptr_t data) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   487
  const address start = addr_at(0);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   488
  int           range = 0;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   489
  if (MacroAssembler::is_load_narrow_oop(start)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   490
    range = MacroAssembler::patch_load_narrow_oop(start, cast_to_oop <intptr_t> (data));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   491
  } else if (MacroAssembler::is_compare_immediate_narrow_oop(start)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   492
    range = MacroAssembler::patch_compare_immediate_narrow_oop(start, cast_to_oop <intptr_t>(data));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   493
  } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   494
    fatal("this is not a `NativeMovConstReg::narrow_oop' site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   495
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   496
  ICache::invalidate_range(start, range);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   497
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   498
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   499
// Compressed klass ptrs. patch narrow klass constant.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   500
void NativeMovConstReg::set_narrow_klass(intptr_t data) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   501
  const address start = addr_at(0);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   502
  int           range = 0;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   503
  if (MacroAssembler::is_load_narrow_klass(start)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   504
    range = MacroAssembler::patch_load_narrow_klass(start, (Klass*)data);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   505
  } else if (MacroAssembler::is_compare_immediate_narrow_klass(start)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   506
    range = MacroAssembler::patch_compare_immediate_narrow_klass(start, (Klass*)data);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   507
  } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   508
    fatal("this is not a `NativeMovConstReg::narrow_klass' site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   509
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   510
  ICache::invalidate_range(start, range);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   511
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   512
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   513
void NativeMovConstReg::set_pcrel_addr(intptr_t newTarget, CompiledMethod *passed_nm /* = NULL */, bool copy_back_to_oop_pool) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   514
  address next_address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   515
  address loc = addr_at(0);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   516
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   517
  if (MacroAssembler::is_load_addr_pcrel(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   518
    address oldTarget = MacroAssembler::get_target_addr_pcrel(loc);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   519
    MacroAssembler::patch_target_addr_pcrel(loc, (address)newTarget);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   520
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   521
    ICache::invalidate_range(loc, MacroAssembler::load_addr_pcrel_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   522
    next_address = loc + MacroAssembler::load_addr_pcrel_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   523
  } else if (MacroAssembler::is_load_const_from_toc_pcrelative(loc) ) {  // Load constant from TOC.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   524
    address oldTarget = MacroAssembler::get_target_addr_pcrel(loc);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   525
    MacroAssembler::patch_target_addr_pcrel(loc, (address)newTarget);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   526
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   527
    ICache::invalidate_range(loc, MacroAssembler::load_const_from_toc_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   528
    next_address = loc + MacroAssembler::load_const_from_toc_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   529
  } else if (MacroAssembler::is_call_far_patchable_pcrelative_at(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   530
    assert(ShortenBranches, "Wait a minute! A pc-relative call w/o ShortenBranches?");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   531
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   532
  } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   533
    assert(false, "Not a NativeMovConstReg site for set_pcrel_addr");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   534
    next_address = next_instruction_address(); // Failure should be handled in next_instruction_address().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   535
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   536
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   537
  if (copy_back_to_oop_pool) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   538
    if (relocInfo::update_oop_pool(instruction_address(), next_address, (address)newTarget, NULL)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   539
      ((NativeMovConstReg*)instruction_address())->dump(64, "NativeMovConstReg::set_pcrel_addr(): found oop reloc for pcrel_addr");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   540
#ifdef LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   541
      VM_Version::z_SIGSEGV();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   542
#else
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   543
      assert(false, "Ooooops: found oop reloc for pcrel_addr");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   544
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   545
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   546
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   547
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   548
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   549
void NativeMovConstReg::set_pcrel_data(intptr_t newData, CompiledMethod *passed_nm /* = NULL */, bool copy_back_to_oop_pool) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   550
  address  next_address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   551
  address  loc = addr_at(0);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   552
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   553
  if (MacroAssembler::is_load_const_from_toc(loc) ) {  // Load constant from TOC.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   554
    // Offset is +/- 2**32 -> use long.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   555
    long     offset  = MacroAssembler::get_load_const_from_toc_offset(loc);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   556
    address  target  = MacroAssembler::get_target_addr_pcrel(loc);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   557
    intptr_t oldData = *(intptr_t*)target;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   558
    if (oldData != newData) { // Update only if data changes. Prevents cache invalidation.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   559
      *(intptr_t *)(target) = newData;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   560
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   561
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   562
    // ICache::invalidate_range(target, sizeof(unsigned long));  // No ICache invalidate for CP data.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   563
    next_address = loc + MacroAssembler::load_const_from_toc_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   564
  } else if (MacroAssembler::is_call_far_pcrelative(loc)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   565
    ((NativeMovConstReg*)loc)->dump(64, "NativeMovConstReg::set_pcrel_data() has a problem: setting data for a pc-relative call?");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   566
#ifdef LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   567
    VM_Version::z_SIGSEGV();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   568
#else
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   569
    assert(false, "Ooooops: setting data for a pc-relative call");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   570
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   571
    next_address = next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   572
  } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   573
    assert(false, "Not a NativeMovConstReg site for set_pcrel_data");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   574
    next_address = next_instruction_address(); // Failure should be handled in next_instruction_address().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   575
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   576
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   577
  if (copy_back_to_oop_pool) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   578
    if (relocInfo::update_oop_pool(instruction_address(), next_address, (address)newData, NULL)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   579
      ((NativeMovConstReg*)instruction_address())->dump(64, "NativeMovConstReg::set_pcrel_data(): found oop reloc for pcrel_data");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   580
#ifdef LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   581
      VM_Version::z_SIGSEGV();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   582
#else
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   583
      assert(false, "Ooooops: found oop reloc for pcrel_data");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   584
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   585
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   586
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   587
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   588
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   589
#ifdef COMPILER1
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   590
//--------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   591
//  N a t i v e M o v R e g M e m
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   592
//--------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   593
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   594
void NativeMovRegMem::verify() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   595
  address l1 = addr_at(0);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   596
  address l2 = addr_at(MacroAssembler::load_const_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   597
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   598
  if (!MacroAssembler::is_load_const(l1)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   599
    tty->cr();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   600
    tty->print_cr("NativeMovRegMem::verify(): verifying addr " PTR_FORMAT, p2i(l1));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   601
    tty->cr();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   602
    ((NativeMovRegMem*)l1)->dump(64, "NativeMovConstReg::verify()");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   603
    fatal("this is not a `NativeMovRegMem' site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   604
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   605
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   606
  unsigned long inst1;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   607
  Assembler::get_instruction(l2, &inst1);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   608
42556
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   609
  if (!Assembler::is_z_lb(inst1)   &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   610
      !Assembler::is_z_llgh(inst1) &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   611
      !Assembler::is_z_lh(inst1)   &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   612
      !Assembler::is_z_l(inst1)    &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   613
      !Assembler::is_z_llgf(inst1) &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   614
      !Assembler::is_z_lg(inst1)   &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   615
      !Assembler::is_z_le(inst1)   &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   616
      !Assembler::is_z_ld(inst1)   &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   617
      !Assembler::is_z_stc(inst1)  &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   618
      !Assembler::is_z_sth(inst1)  &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   619
      !Assembler::is_z_st(inst1)   &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   620
      !UseCompressedOops           &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   621
      !Assembler::is_z_stg(inst1)  &&
c03d98321ad1 8169317: [s390] Various minor bug fixes and adaptions.
goetz
parents: 42065
diff changeset
   622
      !Assembler::is_z_ste(inst1)  &&
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   623
      !Assembler::is_z_std(inst1)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   624
    tty->cr();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   625
    tty->print_cr("NativeMovRegMem::verify(): verifying addr " PTR_FORMAT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   626
                  ": wrong or missing load or store at " PTR_FORMAT, p2i(l1), p2i(l2));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   627
    tty->cr();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   628
    ((NativeMovRegMem*)l1)->dump(64, "NativeMovConstReg::verify()");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   629
    fatal("this is not a `NativeMovRegMem' site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   630
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   631
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   632
#endif // COMPILER1
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   633
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   634
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   635
//  N a t i v e J u m p
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   636
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   637
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   638
void NativeJump::verify() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   639
  if (NativeJump::is_jump_at(addr_at(0))) return;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   640
  fatal("this is not a `NativeJump' site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   641
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   642
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   643
// Patch atomically with an illtrap.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   644
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   645
  ResourceMark rm;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   646
  int code_size = 2;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   647
  CodeBuffer cb(verified_entry, code_size + 1);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   648
  MacroAssembler* a = new MacroAssembler(&cb);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   649
#ifdef COMPILER2
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   650
  assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   651
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   652
  a->z_illtrap();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   653
  ICache::invalidate_range(verified_entry, code_size);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   654
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   655
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   656
#undef LUCY_DBG
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   657
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   658
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   659
//  N a t i v e G e n e r a l J u m p
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   660
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   661
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   662
#ifndef PRODUCT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   663
void NativeGeneralJump::verify() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   664
  unsigned long inst;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   665
  Assembler::get_instruction((address)this, &inst);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   666
  assert(MacroAssembler::is_branch_pcrelative_long(inst), "not a general jump instruction");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   667
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   668
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   669
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   670
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   671
  uint64_t instr = BRCL_ZOPC |
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   672
                   Assembler::uimm4(Assembler::bcondAlways, 8, 48) |
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   673
                   Assembler::simm32(RelAddr::pcrel_off32(entry, code_pos), 16, 48);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   674
  *(uint64_t*) code_pos = (instr << 16); // Must shift into big end, then the brcl will be written to code_pos.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   675
  ICache::invalidate_range(code_pos, instruction_size);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   676
}
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   677
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   678
void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   679
  assert(((intptr_t)instr_addr & (BytesPerWord-1)) == 0, "requirement for mt safe patching");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   680
  // Bytes_after_jump cannot change, because we own the Patching_lock.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   681
  assert(Patching_lock->owned_by_self(), "must hold lock to patch instruction");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   682
  intptr_t bytes_after_jump = (*(intptr_t*)instr_addr)  & 0x000000000000ffffL; // 2 bytes after jump.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   683
  intptr_t load_const_bytes = (*(intptr_t*)code_buffer) & 0xffffffffffff0000L;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   684
  *(intptr_t*)instr_addr = load_const_bytes | bytes_after_jump;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   685
  ICache::invalidate_range(instr_addr, 6);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   686
}