src/hotspot/cpu/s390/nativeInst_s390.hpp
author coleenp
Tue, 27 Mar 2018 11:53:23 -0400
changeset 49621 5ef28d560b6f
parent 49364 601146c66cad
child 52460 f1bb77833b59
permissions -rw-r--r--
8200276: Cleanup allocation.hpp includes Reviewed-by: stefank, hseigel
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42065
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
     1
/*
49364
601146c66cad 8173070: Remove ValueObj class for allocation subclassing for runtime code
coleenp
parents: 47216
diff changeset
     2
 * Copyright (c) 2016, 2018, 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
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    28
#ifndef CPU_S390_VM_NATIVEINST_S390_HPP
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
    29
#define CPU_S390_VM_NATIVEINST_S390_HPP
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
  bool is_memory_serialization(JavaThread *thread, void *ucontext) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   108
    // Is the current instruction a write access of thread to the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   109
    // memory serialization page?
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   110
    return MacroAssembler::is_memory_serialization(long_at(0), thread, ucontext);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   111
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   112
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   113
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   114
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   115
  // The output of __ breakpoint_trap().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   116
  static int illegal_instruction();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   117
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   118
  // The address of the currently processed instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   119
  address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   120
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   121
 protected:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   122
  address addr_at(int offset) const { return address(this) + offset; }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   123
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   124
  // z/Architecture terminology
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   125
  //   halfword   = 2 bytes
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   126
  //   word       = 4 bytes
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   127
  //   doubleword = 8 bytes
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   128
  unsigned short halfword_at(int offset) const { return *(unsigned short*)addr_at(offset); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   129
  int  word_at(int offset)               const { return *(jint*)addr_at(offset); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   130
  long long_at(int offset)               const { return *(jlong*)addr_at(offset); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   131
  void set_halfword_at(int offset, short i); // Deals with I-cache.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   132
  void set_word_at(int offset, int i);       // Deals with I-cache.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   133
  void set_jlong_at(int offset, jlong i);    // Deals with I-cache.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   134
  void set_addr_at(int offset, address x);   // Deals with I-cache.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   135
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   136
  void print() const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   137
  void print(const char* msg) const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   138
  void dump() const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   139
  void dump(const unsigned int range) const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   140
  void dump(const unsigned int range, const char* msg) const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   141
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   142
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   143
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   144
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   145
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   146
  // unit test stuff
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   147
  static void test() {}                        // Override for testing.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   148
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   149
  friend NativeInstruction* nativeInstruction_at(address address) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   150
    NativeInstruction* inst = (NativeInstruction*)address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   151
    #ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   152
      inst->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   153
    #endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   154
    return inst;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   155
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   156
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   157
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   158
//---------------------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   159
//  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
   160
//---------------------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   161
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   162
class NativeIllegalInstruction: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   163
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   164
  enum z_specific_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   165
    instruction_size = 2
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   166
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   167
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   168
  // Insert illegal opcode at specific address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   169
  static void insert(address code_pos);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   170
};
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   171
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   172
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   173
//  N a t i v e C a l l
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   174
//-----------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   175
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   176
// The NativeCall is an abstraction for accessing/manipulating call
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   177
// instructions. It is used to manipulate inline caches, primitive &
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   178
// dll calls, etc.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   179
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   180
// A native call, as defined by this abstraction layer, consists of
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   181
// all instructions required to set up for and actually make the call.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   182
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   183
// On z/Architecture, there exist three different forms of native calls:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   184
// 1) Call with pc-relative address, 1 instruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   185
//    The location of the target function is encoded as relative address
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   186
//    in the call instruction. The short form (BRAS) allows for a
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   187
//    16-bit signed relative address (in 2-byte units). The long form
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   188
//    (BRASL) allows for a 32-bit signed relative address (in 2-byte units).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   189
// 2) Call with immediate address, 3 or 5 instructions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   190
//    The location of the target function is given by an immediate
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   191
//    constant which is loaded into a (scratch) register. Depending on
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   192
//    the hardware capabilities, this takes 2 or 4 instructions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   193
//    The call itself is then a "call by register"(BASR) instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   194
// 3) Call with address from constant pool, 2(3) instructions (with dynamic TOC)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   195
//    The location of the target function is stored in the constant pool
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   196
//    during compilation. From there it is loaded into a (scratch) register.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   197
//    The call itself is then a "call by register"(BASR) instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   198
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   199
// When initially generating a call, the compiler uses form 2) (not
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   200
// patchable, target address constant, e.g. runtime calls) or 3) (patchable,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   201
// target address might eventually get relocated). Later in the process,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   202
// a call could be transformed into form 1) (also patchable) during ShortenBranches.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   203
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   204
// If a call is/has to be patchable, the instruction sequence generated for it
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   205
// has to be constant in length. Excessive space, created e.g. by ShortenBranches,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   206
// is allocated to lower addresses and filled with nops. That is necessary to
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   207
// keep the return address constant, no matter what form the call has.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   208
// Methods dealing with such calls have "patchable" as part of their name.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   209
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   210
class NativeCall: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   211
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   212
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   213
  static int get_IC_pos_in_java_to_interp_stub() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   214
    return 0;
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
  enum z_specific_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   218
    instruction_size                           = 18, // Used in shared code for calls with reloc_info:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   219
                                                     // value correct if !has_long_displacement_fast().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   220
    call_far_pcrelative_displacement_offset    =  4, // Includes 2 bytes for the nop.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   221
    call_far_pcrelative_displacement_alignment =  4
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   222
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   223
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   224
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   225
  // Maximum size (in bytes) of a call to an absolute address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   226
  // Used when emitting call to deopt handler blob, which is a
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   227
  // "load_const_call". The code pattern is:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   228
  //   tmpReg := load_const(address);   (* depends on CPU ArchLvl, but is otherwise constant *)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   229
  //   call(tmpReg);                    (* basr, 2 bytes *)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   230
  static unsigned int max_instruction_size() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   231
    return MacroAssembler::load_const_size() + MacroAssembler::call_byregister_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   232
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   233
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   234
  // address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   235
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   236
  // For the ordering of the checks see note at nativeCall_before.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   237
  address next_instruction_address() const  {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   238
    address iaddr = instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   239
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   240
    if (MacroAssembler::is_load_const_call(iaddr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   241
      // Form 2): load_const, BASR
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   242
      return addr_at(MacroAssembler::load_const_call_size());
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
    if (MacroAssembler::is_load_const_from_toc_call(iaddr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   246
      // Form 3): load_const_from_toc (LARL+LG/LGRL), BASR.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   247
      return addr_at(MacroAssembler::load_const_from_toc_call_size());
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
    if (MacroAssembler::is_call_far_pcrelative(iaddr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   251
      // Form 1): NOP, BRASL
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   252
      // The BRASL (Branch Relative And Save Long) is patched into the space created
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   253
      // by the load_const_from_toc_call sequence (typically (LARL-LG)/LGRL - BASR.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   254
      // 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
   255
      // 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
   256
      // 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
   257
      // be accounted for when calculating the next instruction address. The alignment takes place
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   258
      // already when generating the original instruction sequence. The alignment requirement
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   259
      // makes the size depend on location.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   260
      // 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
   261
      // 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
   262
      // 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
   263
      // distinguish from a load_const_from_toc_call sequence.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   264
      return addr_at(MacroAssembler::call_far_pcrelative_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   265
    }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   266
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   267
    ((NativeCall*)iaddr)->print();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   268
    guarantee(false, "Not a NativeCall site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   269
    return NULL;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   270
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   271
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   272
  address return_address() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   273
    return next_instruction_address();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   274
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   275
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   276
  address destination() const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   277
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   278
  void set_destination_mt_safe(address dest);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   279
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   280
  void verify_alignment() {} // Yet another real do nothing guy :)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   281
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   282
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   283
  // unit test stuff
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   284
  static void test();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   285
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   286
  // Creation.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   287
  friend NativeCall* nativeCall_at(address instr) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   288
    NativeCall* call;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   289
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   290
    // Make sure not to return garbage.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   291
    if (NativeCall::is_call_at(instr)) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   292
      call = (NativeCall*)instr;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   293
    } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   294
      call = (NativeCall*)instr;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   295
      call->print();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   296
      guarantee(false, "Not a NativeCall site");
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
#ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   300
    call->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   301
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   302
    return call;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   303
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   304
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   305
  // This is a very tricky function to implement. It involves stepping
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   306
  // backwards in the instruction stream. On architectures with variable
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   307
  // instruction length, this is a risky endeavor. From the return address,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   308
  // 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
   309
  // point) that will eventually bring you back to the return address.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   310
  // Furthermore, it may happen that there are multiple starting points.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   311
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   312
  // With only a few possible (allowed) code patterns, the risk is lower but
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   313
  // does not diminish completely. Experience shows that there are code patterns
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   314
  // which look like a load_const_from_toc_call @(return address-8), but in
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   315
  // fact are a call_far_pcrelative @(return address-6). The other way around
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   316
  // is possible as well, but was not knowingly observed so far.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   317
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   318
  // The unpredictability is caused by the pc-relative address field in both
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   319
  // the call_far_pcrelative (BASR) and the load_const_from_toc (LGRL)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   320
  // instructions. This field can contain an arbitrary bit pattern.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   321
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   322
  // Here is a real-world example:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   323
  // Mnemonics: <not a valid sequence>   LGRL r10,<addr> BASR r14,r10
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   324
  // Hex code:  eb01 9008 007a c498 ffff c4a8 c0e5 ffc1 0dea
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   325
  // Mnemonics: AGSI <mem>,I8  LGRL r9,<addr> BRASL r14,<addr>  correct
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   326
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   327
  // 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
   328
  // a false positive. In this example, it is obviously false, because the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   329
  // preceding bytes do not form a valid instruction pattern. If you first
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   330
  // check for call_far_pcrelative @(-6), you get a true positive - in this
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   331
  // case.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   332
  //
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   333
  // The following remedy has been implemented/enforced:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   334
  // 1) Everywhere, the permissible code patterns are checked in the same
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   335
  //    sequence: Form 2) - Form 3) - Form 1).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   336
  // 2) The call_far_pcrelative, which would ideally be just one BRASL
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   337
  //    instruction, is always prepended with a NOP. This measure avoids
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   338
  //    ambiguities with load_const_from_toc_call.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   339
  friend NativeCall* nativeCall_before(address return_address) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   340
    NativeCall *call = NULL;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   341
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   342
    // Make sure not to return garbage
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   343
    address instp = return_address - MacroAssembler::load_const_call_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   344
    if (MacroAssembler::is_load_const_call(instp)) {                 // Form 2)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   345
      call = (NativeCall*)(instp);                                   // load_const + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   346
    } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   347
      instp = return_address - MacroAssembler::load_const_from_toc_call_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   348
      if (MacroAssembler::is_load_const_from_toc_call(instp)) {      // Form 3)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   349
        call = (NativeCall*)(instp);                                 // load_const_from_toc + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   350
      } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   351
        instp = return_address - MacroAssembler::call_far_pcrelative_size();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   352
        if (MacroAssembler::is_call_far_pcrelative(instp)) {         // Form 1)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   353
          call = (NativeCall*)(instp);                               // brasl (or nop + brasl)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   354
        } else {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   355
          call = (NativeCall*)(instp);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   356
          call->print();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   357
          guarantee(false, "Not a NativeCall site");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   358
        }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   359
      }
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
#ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   363
    call->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   364
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   365
    return call;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   366
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   367
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   368
  // Ordering of checks 2) 3) 1) is relevant!
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   369
  static bool is_call_at(address a) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   370
    // Check plain instruction sequence. Do not care about filler or alignment nops.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   371
    bool b = MacroAssembler::is_load_const_call(a) ||           // load_const + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   372
             MacroAssembler::is_load_const_from_toc_call(a) ||  // load_const_from_toc + basr
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   373
             MacroAssembler::is_call_far_pcrelative(a);         // nop + brasl
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   374
    return b;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   375
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   376
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   377
  // Ordering of checks 2) 3) 1) is relevant!
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   378
  static bool is_call_before(address a) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   379
    // check plain instruction sequence. Do not care about filler or alignment nops.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   380
    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
   381
             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
   382
             MacroAssembler::is_call_far_pcrelative(     a - MacroAssembler::call_far_pcrelative_size());         // nop+brasl
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   383
    return b;
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
  static bool is_call_to(address instr, address target) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   387
    // Check whether there is a `NativeCall' at the address `instr'
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   388
    // calling to the address `target'.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   389
    return is_call_at(instr) && target == ((NativeCall *)instr)->destination();
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
  bool is_pcrelative() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   393
    return MacroAssembler::is_call_far_pcrelative((address)this);
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
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   397
//-----------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   398
//  N a t i v e F a r C a l l
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   399
//-----------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   400
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   401
// The NativeFarCall is an abstraction for accessing/manipulating native
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   402
// call-anywhere instructions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   403
// Used to call native methods which may be loaded anywhere in the address
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   404
// space, possibly out of reach of a call instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   405
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   406
// Refer to NativeCall for a description of the supported call forms.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   407
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   408
class NativeFarCall: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   409
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   410
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   411
  // We use MacroAssembler::call_far_patchable() for implementing a
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   412
  // call-anywhere instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   413
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   414
  static int instruction_size()      { return MacroAssembler::call_far_patchable_size(); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   415
  static int return_address_offset() { return MacroAssembler::call_far_patchable_ret_addr_offset(); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   416
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   417
  // address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   418
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   419
  address next_instruction_address() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   420
    return addr_at(instruction_size());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   421
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   422
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   423
  address return_address() const {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   424
    return addr_at(return_address_offset());
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   425
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   426
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   427
  // Returns the NativeFarCall's destination.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   428
  address destination();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   429
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   430
  // Sets the NativeCall's destination, not necessarily mt-safe.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   431
  // Used when relocating code.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   432
  void set_destination(address dest, int toc_offset);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   433
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   434
  // Checks whether instr points at a NativeFarCall instruction.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   435
  static bool is_far_call_at(address instr) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   436
    // Use compound inspection function which, in addition to instruction sequence,
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   437
    // also checks for expected nops and for instruction alignment.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   438
    return MacroAssembler::is_call_far_patchable_at(instr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   439
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   440
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   441
  // Does the NativeFarCall implementation use a pc-relative encoding
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   442
  // of the call destination?
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   443
  // Used when relocating code.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   444
  bool is_pcrelative() {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   445
    address iaddr = (address)this;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   446
    assert(is_far_call_at(iaddr), "unexpected call type");
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   447
    return MacroAssembler::is_call_far_patchable_pcrelative_at(iaddr);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   448
  }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   449
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   450
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   451
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   452
  // Unit tests
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   453
  static void test();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   454
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   455
  // Instantiates a NativeFarCall object starting at the given instruction
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   456
  // address and returns the NativeFarCall object.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   457
  inline friend NativeFarCall* nativeFarCall_at(address instr) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   458
    NativeFarCall* call = (NativeFarCall*)instr;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   459
#ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   460
    call->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   461
#endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   462
    return call;
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
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   466
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   467
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   468
//  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
   469
//-------------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   470
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   471
// An interface for accessing/manipulating native set_oop imm, reg instructions.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   472
// (Used to manipulate inlined data references, etc.)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   473
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   474
// 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
   475
// deals with instruction sequences that load "quasi constant" oops into registers
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   476
// for addressing. For multiple causes, those "quasi constant" oops eventually need
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   477
// 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
   478
// around in storage. Pc-relative oop addresses have to be patched also if the
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   479
// reference location is moved. That happens when executable code is relocated.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   480
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   481
class NativeMovConstReg: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   482
 public:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   483
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   484
  enum z_specific_constants {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   485
    instruction_size = 10 // Used in shared code for calls with reloc_info.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   486
  };
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   487
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   488
  // address instruction_address() const { return addr_at(0); }
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   489
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   490
  // The current instruction might be located at an offset.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   491
  address next_instruction_address(int offset = 0) const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   492
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   493
  // (The [set_]data accessor respects oop_type relocs also.)
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   494
  intptr_t data() const;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   495
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   496
  // Patch data in code stream.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   497
  address set_data_plain(intptr_t x, CodeBlob *code);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   498
  // Patch data in code stream and oop pool if necessary.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   499
  void set_data(intptr_t x);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   500
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   501
  // Patch narrow oop constant in code stream.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   502
  void set_narrow_oop(intptr_t data);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   503
  void set_narrow_klass(intptr_t data);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   504
  void set_pcrel_addr(intptr_t addr, CompiledMethod *nm = NULL, bool copy_back_to_oop_pool=false);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   505
  void set_pcrel_data(intptr_t data, CompiledMethod *nm = NULL, bool copy_back_to_oop_pool=false);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   506
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   507
  void verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   508
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   509
  // unit test stuff
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   510
  static void test();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   511
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   512
  // Creation.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   513
  friend NativeMovConstReg* nativeMovConstReg_at(address address) {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   514
    NativeMovConstReg* test = (NativeMovConstReg*)address;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   515
    #ifdef ASSERT
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   516
      test->verify();
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   517
    #endif
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   518
    return test;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   519
  }
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
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   523
#ifdef COMPILER1
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   524
//---------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   525
//  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
   526
//---------------------------------
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   527
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   528
// Interface to manipulate a code sequence that performs a memory access (load/store).
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   529
// The code is the patchable version of memory accesses generated by
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   530
// LIR_Assembler::reg2mem() and LIR_Assembler::mem2reg().
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   531
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   532
// Loading the offset for the mem access is target of the manipulation.
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   533
//
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   534
// The instruction sequence looks like this:
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   535
//   iihf        %r1,$bits1              ; load offset for mem access
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   536
//   iilf        %r1,$bits2
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   537
//   [compress oop]                      ; optional, load only
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   538
//   load/store  %r2,0(%r1,%r2)          ; memory access
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   539
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   540
class NativeMovRegMem;
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   541
inline NativeMovRegMem* nativeMovRegMem_at (address address);
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   542
class NativeMovRegMem: public NativeInstruction {
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   543
 public:
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
6032b31e3719 8167673: [s390] The s390 port.
goetz
parents:
diff changeset
   672
#endif // CPU_S390_VM_NATIVEINST_S390_HPP