src/hotspot/cpu/s390/nativeInst_s390.hpp
author mdoerr
Tue, 05 Nov 2019 11:53:46 +0100
changeset 58932 8623f75be895
parent 57583 aad50831e169
permissions -rw-r--r--
8233081: C1: PatchingStub for field access copies too much Reviewed-by: thartmann, dlong
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     1
/*
53244
9807daeb47c4 8216167: Update include guards to reflect correct directories
coleenp
parents: 52460
diff changeset
     2
 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
42065
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 AHa, JL, LS
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    27
53244
9807daeb47c4 8216167: Update include guards to reflect correct directories
coleenp
parents: 52460
diff changeset
    28
#ifndef CPU_S390_NATIVEINST_S390_HPP
9807daeb47c4 8216167: Update include guards to reflect correct directories
coleenp
parents: 52460
diff changeset
    29
#define CPU_S390_NATIVEINST_S390_HPP
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    30
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    31
#include "asm/macroAssembler.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    32
#include "runtime/icache.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    33
#include "runtime/os.hpp"
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    34
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    35
class NativeCall;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    36
class NativeFarCall;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    37
class NativeMovConstReg;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    38
class NativeJump;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    39
#ifndef COMPILER2
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    40
class NativeGeneralJump;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    41
class NativeMovRegMem;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    42
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    43
class NativeInstruction;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    44
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    45
NativeCall* nativeCall_before(address return_address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    46
NativeCall* nativeCall_at(address instr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    47
NativeFarCall* nativeFarCall_before(address return_address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    48
NativeFarCall* nativeFarCall_at(address instr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    49
NativeMovConstReg* nativeMovConstReg_at(address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    50
NativeMovConstReg* nativeMovConstReg_before(address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    51
NativeJump* nativeJump_at(address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    52
#ifndef COMPILER2
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    53
NativeMovRegMem* nativeMovRegMem_at (address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    54
NativeGeneralJump* nativeGeneralJump_at(address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    55
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    56
NativeInstruction* nativeInstruction_at(address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    57
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    58
// We have interface for the following instructions:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    59
// - NativeInstruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    60
//   - NativeCall
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    61
//   - NativeFarCall
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    62
//   - NativeMovConstReg
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    63
//   - NativeMovRegMem
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    64
//   - NativeJump
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    65
//   - NativeGeneralJump
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    66
//   - NativeIllegalInstruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    67
// The base class for different kinds of native instruction abstractions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    68
// Provides the primitive operations to manipulate code relative to this.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    69
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    70
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    71
//  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
    72
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    73
49364
601146c66cad 8173070: Remove ValueObj class for allocation subclassing for runtime code
coleenp
parents: 47216
diff changeset
    74
class NativeInstruction {
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    75
  friend class Relocation;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    76
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    77
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    78
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    79
  enum z_specific_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    80
    nop_instruction_size = 2
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    81
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    82
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    83
  bool is_illegal();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    84
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    85
  // Bcrl is currently the only accepted instruction here.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    86
  bool is_jump();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    87
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    88
  // We use an illtrap for marking a method as not_entrant or zombie.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    89
  bool is_sigill_zombie_not_entrant();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    90
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    91
  bool is_safepoint_poll() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    92
    // Is the current instruction a POTENTIAL read access to the polling page?
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    93
    // The instruction's current arguments are not checked!
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    94
    return MacroAssembler::is_load_from_polling_page(addr_at(0));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    95
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    96
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    97
  address get_poll_address(void *ucontext) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    98
    // Extract poll address from instruction and ucontext.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    99
    return MacroAssembler::get_poll_address(addr_at(0), ucontext);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   100
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   101
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   102
  uint get_poll_register() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   103
    // Extract poll register from instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   104
    return MacroAssembler::get_poll_register(addr_at(0));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   105
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   106
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   107
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   108
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   109
  // The output of __ breakpoint_trap().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   110
  static int illegal_instruction();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   111
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   112
  // The address of the currently processed instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   113
  address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   114
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   115
 protected:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   116
  address addr_at(int offset) const { return address(this) + offset; }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   117
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   118
  // z/Architecture terminology
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   119
  //   halfword   = 2 bytes
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   120
  //   word       = 4 bytes
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   121
  //   doubleword = 8 bytes
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   122
  unsigned short halfword_at(int offset) const { return *(unsigned short*)addr_at(offset); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   123
  int  word_at(int offset)               const { return *(jint*)addr_at(offset); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   124
  long long_at(int offset)               const { return *(jlong*)addr_at(offset); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   125
  void set_halfword_at(int offset, short i); // Deals with I-cache.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   126
  void set_word_at(int offset, int i);       // Deals with I-cache.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   127
  void set_jlong_at(int offset, jlong i);    // Deals with I-cache.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   128
  void set_addr_at(int offset, address x);   // Deals with I-cache.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   129
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   130
  void print() const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   131
  void print(const char* msg) const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   132
  void dump() const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   133
  void dump(const unsigned int range) const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   134
  void dump(const unsigned int range, const char* msg) const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   135
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   136
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   137
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   138
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   139
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   140
  // unit test stuff
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   141
  static void test() {}                        // Override for testing.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   142
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   143
  friend NativeInstruction* nativeInstruction_at(address address) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   144
    NativeInstruction* inst = (NativeInstruction*)address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   145
    #ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   146
      inst->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   147
    #endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   148
    return inst;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   149
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   150
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   151
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   152
//---------------------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   153
//  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
   154
//---------------------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   155
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   156
class NativeIllegalInstruction: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   157
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   158
  enum z_specific_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   159
    instruction_size = 2
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   160
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   161
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   162
  // Insert illegal opcode at specific address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   163
  static void insert(address code_pos);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   164
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   165
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   166
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   167
//  N a t i v e C a l l
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   168
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   169
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   170
// The NativeCall is an abstraction for accessing/manipulating call
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   171
// instructions. It is used to manipulate inline caches, primitive &
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   172
// dll calls, etc.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   173
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   174
// A native call, as defined by this abstraction layer, consists of
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   175
// all instructions required to set up for and actually make the call.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   176
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   177
// On z/Architecture, there exist three different forms of native calls:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   178
// 1) Call with pc-relative address, 1 instruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   179
//    The location of the target function is encoded as relative address
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   180
//    in the call instruction. The short form (BRAS) allows for a
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   181
//    16-bit signed relative address (in 2-byte units). The long form
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   182
//    (BRASL) allows for a 32-bit signed relative address (in 2-byte units).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   183
// 2) Call with immediate address, 3 or 5 instructions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   184
//    The location of the target function is given by an immediate
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   185
//    constant which is loaded into a (scratch) register. Depending on
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   186
//    the hardware capabilities, this takes 2 or 4 instructions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   187
//    The call itself is then a "call by register"(BASR) instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   188
// 3) Call with address from constant pool, 2(3) instructions (with dynamic TOC)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   189
//    The location of the target function is stored in the constant pool
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   190
//    during compilation. From there it is loaded into a (scratch) register.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   191
//    The call itself is then a "call by register"(BASR) instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   192
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   193
// When initially generating a call, the compiler uses form 2) (not
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   194
// patchable, target address constant, e.g. runtime calls) or 3) (patchable,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   195
// target address might eventually get relocated). Later in the process,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   196
// a call could be transformed into form 1) (also patchable) during ShortenBranches.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   197
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   198
// If a call is/has to be patchable, the instruction sequence generated for it
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   199
// has to be constant in length. Excessive space, created e.g. by ShortenBranches,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   200
// is allocated to lower addresses and filled with nops. That is necessary to
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   201
// keep the return address constant, no matter what form the call has.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   202
// Methods dealing with such calls have "patchable" as part of their name.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   203
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   204
class NativeCall: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   205
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   206
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   207
  static int get_IC_pos_in_java_to_interp_stub() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   208
    return 0;
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
  enum z_specific_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   212
    instruction_size                           = 18, // Used in shared code for calls with reloc_info:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   213
                                                     // value correct if !has_long_displacement_fast().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   214
    call_far_pcrelative_displacement_offset    =  4, // Includes 2 bytes for the nop.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   215
    call_far_pcrelative_displacement_alignment =  4
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   216
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   217
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   218
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   219
  // Maximum size (in bytes) of a call to an absolute address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   220
  // Used when emitting call to deopt handler blob, which is a
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   221
  // "load_const_call". The code pattern is:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   222
  //   tmpReg := load_const(address);   (* depends on CPU ArchLvl, but is otherwise constant *)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   223
  //   call(tmpReg);                    (* basr, 2 bytes *)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   224
  static unsigned int max_instruction_size() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   225
    return MacroAssembler::load_const_size() + MacroAssembler::call_byregister_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   226
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   227
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   228
  // address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   229
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   230
  // For the ordering of the checks see note at nativeCall_before.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   231
  address next_instruction_address() const  {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   232
    address iaddr = instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   233
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   234
    if (MacroAssembler::is_load_const_call(iaddr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   235
      // Form 2): load_const, BASR
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   236
      return addr_at(MacroAssembler::load_const_call_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   237
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   238
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   239
    if (MacroAssembler::is_load_const_from_toc_call(iaddr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   240
      // Form 3): load_const_from_toc (LARL+LG/LGRL), BASR.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   241
      return addr_at(MacroAssembler::load_const_from_toc_call_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   242
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   243
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   244
    if (MacroAssembler::is_call_far_pcrelative(iaddr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   245
      // Form 1): NOP, BRASL
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   246
      // The BRASL (Branch Relative And Save Long) is patched into the space created
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   247
      // by the load_const_from_toc_call sequence (typically (LARL-LG)/LGRL - BASR.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   248
      // The BRASL must be positioned such that it's end is FW (4-byte) aligned (for atomic patching).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   249
      // It is achieved by aligning the end of the entire sequence on a 4byte boundary, by inserting
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   250
      // a nop, if required, at the very beginning of the instruction sequence. The nop needs to
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   251
      // be accounted for when calculating the next instruction address. The alignment takes place
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   252
      // already when generating the original instruction sequence. The alignment requirement
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   253
      // makes the size depend on location.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   254
      // The return address of the call must always be at the end of the instruction sequence.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   255
      // Inserting the extra alignment nop (or anything else) at the end is not an option.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   256
      // The patched-in brasl instruction is prepended with a nop to make it easier to
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   257
      // distinguish from a load_const_from_toc_call sequence.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   258
      return addr_at(MacroAssembler::call_far_pcrelative_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   259
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   260
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   261
    ((NativeCall*)iaddr)->print();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   262
    guarantee(false, "Not a NativeCall site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   263
    return NULL;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   264
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   265
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   266
  address return_address() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   267
    return next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   268
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   269
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   270
  address destination() const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   271
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   272
  void set_destination_mt_safe(address dest);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   273
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   274
  void verify_alignment() {} // Yet another real do nothing guy :)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   275
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   276
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   277
  // unit test stuff
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   278
  static void test();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   279
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   280
  // Creation.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   281
  friend NativeCall* nativeCall_at(address instr) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   282
    NativeCall* call;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   283
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   284
    // Make sure not to return garbage.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   285
    if (NativeCall::is_call_at(instr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   286
      call = (NativeCall*)instr;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   287
    } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   288
      call = (NativeCall*)instr;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   289
      call->print();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   290
      guarantee(false, "Not a NativeCall site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   291
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   292
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   293
#ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   294
    call->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   295
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   296
    return call;
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
  // This is a very tricky function to implement. It involves stepping
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   300
  // backwards in the instruction stream. On architectures with variable
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   301
  // instruction length, this is a risky endeavor. From the return address,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   302
  // you do not know how far to step back to be at a location (your starting
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   303
  // point) that will eventually bring you back to the return address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   304
  // Furthermore, it may happen that there are multiple starting points.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   305
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   306
  // With only a few possible (allowed) code patterns, the risk is lower but
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   307
  // does not diminish completely. Experience shows that there are code patterns
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   308
  // which look like a load_const_from_toc_call @(return address-8), but in
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   309
  // fact are a call_far_pcrelative @(return address-6). The other way around
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   310
  // is possible as well, but was not knowingly observed so far.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   311
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   312
  // The unpredictability is caused by the pc-relative address field in both
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   313
  // the call_far_pcrelative (BASR) and the load_const_from_toc (LGRL)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   314
  // instructions. This field can contain an arbitrary bit pattern.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   315
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   316
  // Here is a real-world example:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   317
  // Mnemonics: <not a valid sequence>   LGRL r10,<addr> BASR r14,r10
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   318
  // Hex code:  eb01 9008 007a c498 ffff c4a8 c0e5 ffc1 0dea
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   319
  // Mnemonics: AGSI <mem>,I8  LGRL r9,<addr> BRASL r14,<addr>  correct
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   320
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   321
  // If you first check for a load_const_from_toc_call @(-8), you will find
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   322
  // a false positive. In this example, it is obviously false, because the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   323
  // preceding bytes do not form a valid instruction pattern. If you first
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   324
  // check for call_far_pcrelative @(-6), you get a true positive - in this
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   325
  // case.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   326
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   327
  // The following remedy has been implemented/enforced:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   328
  // 1) Everywhere, the permissible code patterns are checked in the same
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   329
  //    sequence: Form 2) - Form 3) - Form 1).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   330
  // 2) The call_far_pcrelative, which would ideally be just one BRASL
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   331
  //    instruction, is always prepended with a NOP. This measure avoids
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   332
  //    ambiguities with load_const_from_toc_call.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   333
  friend NativeCall* nativeCall_before(address return_address) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   334
    NativeCall *call = NULL;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   335
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   336
    // Make sure not to return garbage
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   337
    address instp = return_address - MacroAssembler::load_const_call_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   338
    if (MacroAssembler::is_load_const_call(instp)) {                 // Form 2)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   339
      call = (NativeCall*)(instp);                                   // load_const + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   340
    } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   341
      instp = return_address - MacroAssembler::load_const_from_toc_call_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   342
      if (MacroAssembler::is_load_const_from_toc_call(instp)) {      // Form 3)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   343
        call = (NativeCall*)(instp);                                 // load_const_from_toc + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   344
      } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   345
        instp = return_address - MacroAssembler::call_far_pcrelative_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   346
        if (MacroAssembler::is_call_far_pcrelative(instp)) {         // Form 1)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   347
          call = (NativeCall*)(instp);                               // brasl (or nop + brasl)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   348
        } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   349
          call = (NativeCall*)(instp);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   350
          call->print();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   351
          guarantee(false, "Not a NativeCall site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   352
        }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   353
      }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   354
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   355
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   356
#ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   357
    call->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   358
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   359
    return call;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   360
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   361
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   362
  // Ordering of checks 2) 3) 1) is relevant!
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   363
  static bool is_call_at(address a) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   364
    // Check plain instruction sequence. Do not care about filler or alignment nops.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   365
    bool b = MacroAssembler::is_load_const_call(a) ||           // load_const + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   366
             MacroAssembler::is_load_const_from_toc_call(a) ||  // load_const_from_toc + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   367
             MacroAssembler::is_call_far_pcrelative(a);         // nop + brasl
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   368
    return b;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   369
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   370
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   371
  // Ordering of checks 2) 3) 1) is relevant!
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   372
  static bool is_call_before(address a) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   373
    // check plain instruction sequence. Do not care about filler or alignment nops.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   374
    bool b = MacroAssembler::is_load_const_call(         a - MacroAssembler::load_const_call_size()) ||           // load_const + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   375
             MacroAssembler::is_load_const_from_toc_call(a - MacroAssembler::load_const_from_toc_call_size()) ||  // load_const_from_toc + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   376
             MacroAssembler::is_call_far_pcrelative(     a - MacroAssembler::call_far_pcrelative_size());         // nop+brasl
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   377
    return b;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   378
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   379
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   380
  static bool is_call_to(address instr, address target) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   381
    // Check whether there is a `NativeCall' at the address `instr'
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   382
    // calling to the address `target'.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   383
    return is_call_at(instr) && target == ((NativeCall *)instr)->destination();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   384
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   385
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   386
  bool is_pcrelative() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   387
    return MacroAssembler::is_call_far_pcrelative((address)this);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   388
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   389
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   390
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   391
//-----------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   392
//  N a t i v e F a r C a l l
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
// The NativeFarCall is an abstraction for accessing/manipulating native
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   396
// call-anywhere instructions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   397
// Used to call native methods which may be loaded anywhere in the address
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   398
// space, possibly out of reach of a call instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   399
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   400
// Refer to NativeCall for a description of the supported call forms.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   401
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   402
class NativeFarCall: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   403
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   404
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   405
  // We use MacroAssembler::call_far_patchable() for implementing a
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   406
  // call-anywhere instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   407
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   408
  static int instruction_size()      { return MacroAssembler::call_far_patchable_size(); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   409
  static int return_address_offset() { return MacroAssembler::call_far_patchable_ret_addr_offset(); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   410
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   411
  // address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   412
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   413
  address next_instruction_address() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   414
    return addr_at(instruction_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   415
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   416
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   417
  address return_address() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   418
    return addr_at(return_address_offset());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   419
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   420
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   421
  // Returns the NativeFarCall's destination.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   422
  address destination();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   423
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   424
  // Sets the NativeCall's destination, not necessarily mt-safe.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   425
  // Used when relocating code.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   426
  void set_destination(address dest, int toc_offset);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   427
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   428
  // Checks whether instr points at a NativeFarCall instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   429
  static bool is_far_call_at(address instr) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   430
    // Use compound inspection function which, in addition to instruction sequence,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   431
    // also checks for expected nops and for instruction alignment.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   432
    return MacroAssembler::is_call_far_patchable_at(instr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   433
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   434
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   435
  // Does the NativeFarCall implementation use a pc-relative encoding
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   436
  // of the call destination?
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   437
  // Used when relocating code.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   438
  bool is_pcrelative() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   439
    address iaddr = (address)this;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   440
    assert(is_far_call_at(iaddr), "unexpected call type");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   441
    return MacroAssembler::is_call_far_patchable_pcrelative_at(iaddr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   442
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   443
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   444
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   445
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   446
  // Unit tests
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   447
  static void test();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   448
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   449
  // Instantiates a NativeFarCall object starting at the given instruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   450
  // address and returns the NativeFarCall object.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   451
  inline friend NativeFarCall* nativeFarCall_at(address instr) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   452
    NativeFarCall* call = (NativeFarCall*)instr;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   453
#ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   454
    call->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   455
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   456
    return call;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   457
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   458
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   459
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   460
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   461
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   462
//  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
   463
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   464
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   465
// An interface for accessing/manipulating native set_oop imm, reg instructions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   466
// (Used to manipulate inlined data references, etc.)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   467
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   468
// A native move of a constant into a register, as defined by this abstraction layer,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   469
// deals with instruction sequences that load "quasi constant" oops into registers
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   470
// for addressing. For multiple causes, those "quasi constant" oops eventually need
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   471
// to be changed (i.e. patched). The reason is quite simple: objects might get moved
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   472
// around in storage. Pc-relative oop addresses have to be patched also if the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   473
// reference location is moved. That happens when executable code is relocated.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   474
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   475
class NativeMovConstReg: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   476
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   477
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   478
  enum z_specific_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   479
    instruction_size = 10 // Used in shared code for calls with reloc_info.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   480
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   481
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   482
  // address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   483
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   484
  // The current instruction might be located at an offset.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   485
  address next_instruction_address(int offset = 0) const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   486
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   487
  // (The [set_]data accessor respects oop_type relocs also.)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   488
  intptr_t data() const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   489
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   490
  // Patch data in code stream.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   491
  address set_data_plain(intptr_t x, CodeBlob *code);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   492
  // Patch data in code stream and oop pool if necessary.
57583
aad50831e169 8228618: s390: c1/c2 fail to add a metadata relocation in the static call stub.
rrich
parents: 53244
diff changeset
   493
  void set_data(intptr_t x, relocInfo::relocType expected_type = relocInfo::none);
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   494
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   495
  // Patch narrow oop constant in code stream.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   496
  void set_narrow_oop(intptr_t data);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   497
  void set_narrow_klass(intptr_t data);
57583
aad50831e169 8228618: s390: c1/c2 fail to add a metadata relocation in the static call stub.
rrich
parents: 53244
diff changeset
   498
  void set_pcrel_addr(intptr_t addr, CompiledMethod *nm = NULL);
aad50831e169 8228618: s390: c1/c2 fail to add a metadata relocation in the static call stub.
rrich
parents: 53244
diff changeset
   499
  void set_pcrel_data(intptr_t data, CompiledMethod *nm = NULL);
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   500
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   501
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   502
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   503
  // unit test stuff
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   504
  static void test();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   505
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   506
  // Creation.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   507
  friend NativeMovConstReg* nativeMovConstReg_at(address address) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   508
    NativeMovConstReg* test = (NativeMovConstReg*)address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   509
    #ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   510
      test->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   511
    #endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   512
    return test;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   513
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   514
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   515
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   516
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   517
#ifdef COMPILER1
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   518
//---------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   519
//  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
   520
//---------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   521
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   522
// Interface to manipulate a code sequence that performs a memory access (load/store).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   523
// The code is the patchable version of memory accesses generated by
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   524
// LIR_Assembler::reg2mem() and LIR_Assembler::mem2reg().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   525
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   526
// Loading the offset for the mem access is target of the manipulation.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   527
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   528
// The instruction sequence looks like this:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   529
//   iihf        %r1,$bits1              ; load offset for mem access
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   530
//   iilf        %r1,$bits2
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   531
//   [compress oop]                      ; optional, load only
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   532
//   load/store  %r2,0(%r1,%r2)          ; memory access
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   533
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   534
class NativeMovRegMem;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   535
inline NativeMovRegMem* nativeMovRegMem_at (address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   536
class NativeMovRegMem: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   537
 public:
58932
8623f75be895 8233081: C1: PatchingStub for field access copies too much
mdoerr
parents: 57583
diff changeset
   538
  enum z_specific_constants {
8623f75be895 8233081: C1: PatchingStub for field access copies too much
mdoerr
parents: 57583
diff changeset
   539
    instruction_size = 12 // load_const used with access_field_id
8623f75be895 8233081: C1: PatchingStub for field access copies too much
mdoerr
parents: 57583
diff changeset
   540
  };
8623f75be895 8233081: C1: PatchingStub for field access copies too much
mdoerr
parents: 57583
diff changeset
   541
8623f75be895 8233081: C1: PatchingStub for field access copies too much
mdoerr
parents: 57583
diff changeset
   542
  int num_bytes_to_end_of_patch() const { return instruction_size; }
8623f75be895 8233081: C1: PatchingStub for field access copies too much
mdoerr
parents: 57583
diff changeset
   543
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   544
  intptr_t offset() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   545
    return nativeMovConstReg_at(addr_at(0))->data();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   546
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   547
  void set_offset(intptr_t x) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   548
    nativeMovConstReg_at(addr_at(0))->set_data(x);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   549
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   550
  void add_offset_in_bytes(intptr_t radd_offset) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   551
    set_offset(offset() + radd_offset);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   552
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   553
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   554
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   555
 private:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   556
  friend inline NativeMovRegMem* nativeMovRegMem_at(address address) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   557
    NativeMovRegMem* test = (NativeMovRegMem*)address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   558
    #ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   559
      test->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   560
    #endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   561
    return test;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   562
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   563
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   564
#endif // COMPILER1
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   565
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   566
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   567
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   568
//  N a t i v e J u m p
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   569
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   570
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   571
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   572
// An interface for accessing/manipulating native jumps
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   573
class NativeJump: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   574
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   575
  enum z_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   576
    instruction_size = 2 // Size of z_illtrap().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   577
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   578
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   579
  // Maximum size (in bytes) of a jump to an absolute address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   580
  // Used when emitting branch to an exception handler which is a "load_const_optimized_branch".
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   581
  // Thus, a pessimistic estimate is obtained when using load_const.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   582
  // code pattern is:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   583
  //   tmpReg := load_const(address);   (* varying size *)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   584
  //   jumpTo(tmpReg);                  (* bcr, 2 bytes *)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   585
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   586
  static unsigned int max_instruction_size() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   587
    return MacroAssembler::load_const_size() + MacroAssembler::jump_byregister_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   588
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   589
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   590
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   591
//  address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   592
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   593
  address jump_destination() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   594
    return (address)nativeMovConstReg_at(instruction_address())->data();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   595
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   596
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   597
  void set_jump_destination(address dest) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   598
    nativeMovConstReg_at(instruction_address())->set_data(((intptr_t)dest));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   599
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   600
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   601
  // Creation
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   602
  friend NativeJump* nativeJump_at(address address) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   603
    NativeJump* jump = (NativeJump*)address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   604
    #ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   605
      jump->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   606
    #endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   607
    return jump;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   608
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   609
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   610
  static bool is_jump_at(address a) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   611
    int off = 0;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   612
    bool b = (MacroAssembler::is_load_const_from_toc(a+off) &&
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   613
              Assembler::is_z_br(*(short*)(a+off + MacroAssembler::load_const_from_toc_size())));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   614
    b = b || (MacroAssembler::is_load_const(a+off) &&
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   615
              Assembler::is_z_br(*(short*)(a+off + MacroAssembler::load_const_size())));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   616
    return b;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   617
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   618
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   619
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   620
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   621
  // Unit testing stuff
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   622
  static void test();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   623
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   624
  // Insertion of native jump instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   625
  static void insert(address code_pos, address entry);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   626
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   627
  // MT-safe insertion of native jump at verified method entry.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   628
  static void check_verified_entry_alignment(address entry, address verified_entry) { }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   629
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   630
  static void patch_verified_entry(address entry, address verified_entry, address dest);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   631
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   632
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   633
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   634
//  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
   635
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   636
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   637
// Despite the name, handles only simple branches.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   638
// On ZARCH_64 BRCL only.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   639
class NativeGeneralJump;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   640
inline NativeGeneralJump* nativeGeneralJump_at(address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   641
class NativeGeneralJump: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   642
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   643
  enum ZARCH_specific_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   644
    instruction_size = 6
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   645
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   646
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   647
  address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   648
  address jump_destination()    const { return addr_at(0) + MacroAssembler::get_pcrel_offset(addr_at(0)); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   649
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   650
  // Creation
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   651
  friend inline NativeGeneralJump* nativeGeneralJump_at(address addr) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   652
    NativeGeneralJump* jump = (NativeGeneralJump*)(addr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   653
#ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   654
    jump->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   655
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   656
    return jump;
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
  // Insertion of native general jump instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   660
  static void insert_unconditional(address code_pos, address entry);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   661
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   662
  void set_jump_destination(address dest) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   663
    Unimplemented();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   664
    // set_word_at(MacroAssembler::call_far_pcrelative_size()-4, Assembler::z_pcrel_off(dest, addr_at(0)));
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   665
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   666
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   667
  static void replace_mt_safe(address instr_addr, address code_buffer);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   668
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   669
  void verify() PRODUCT_RETURN;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   670
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   671
53244
9807daeb47c4 8216167: Update include guards to reflect correct directories
coleenp
parents: 52460
diff changeset
   672
#endif // CPU_S390_NATIVEINST_S390_HPP