hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp
author mikael
Tue, 29 Apr 2014 22:05:10 -0700
changeset 24327 d8d91481f76e
parent 22234 da823d78ad65
child 24930 1fc3041c8e78
permissions -rw-r--r--
8042059: Various fixes to linux/sparc Reviewed-by: twisti, kvn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
22234
da823d78ad65 8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents: 18097
diff changeset
     2
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 2131
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 2131
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 2131
diff changeset
    21
 * questions.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
7397
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
    25
#ifndef CPU_SPARC_VM_NATIVEINST_SPARC_HPP
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
    26
#define CPU_SPARC_VM_NATIVEINST_SPARC_HPP
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
    27
14631
526804361522 8003250: SPARC: move MacroAssembler into separate file
twisti
parents: 13728
diff changeset
    28
#include "asm/macroAssembler.hpp"
7397
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
    29
#include "memory/allocation.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
    30
#include "runtime/icache.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
    31
#include "runtime/os.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
    32
#include "utilities/top.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
    33
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
// We have interface for the following instructions:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
// - NativeInstruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
// - - NativeCall
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
// - - NativeFarCall
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
// - - NativeMovConstReg
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
// - - NativeMovConstRegPatching
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
// - - NativeMovRegMem
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
// - - NativeMovRegMemPatching
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
// - - NativeJump
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
// - - NativeGeneralJump
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
// - - NativeIllegalInstruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
// The base class for different kinds of native instruction abstractions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
// Provides the primitive operations to manipulate code relative to this.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
class NativeInstruction VALUE_OBJ_CLASS_SPEC {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  friend class Relocation;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
    nop_instruction_size        =    4
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
363
99d43e8a76ad 6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents: 1
diff changeset
    55
  bool is_dtrace_trap();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
  bool is_nop()                        { return long_at(0) == nop_instruction(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
  bool is_call()                       { return is_op(long_at(0), Assembler::call_op); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
  bool is_sethi()                      { return (is_op2(long_at(0), Assembler::sethi_op2)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
                                          && inv_rd(long_at(0)) != G0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
  bool sets_cc() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
    // conservative (returns true for some instructions that do not set the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
    // the condition code, such as, "save".
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
    // Does not return true for the deprecated tagged instructions, such as, TADDcc
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
    return (is_op(x, Assembler::arith_op) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
            (inv_op3(x) & Assembler::cc_bit_op3) == Assembler::cc_bit_op3);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
  bool is_illegal();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
  bool is_zombie() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
    return is_op3(x,
18097
acd70736bd60 8008407: remove SPARC V8 support
morris
parents: 14631
diff changeset
    73
                  Assembler::ldsw_op3,
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
                  Assembler::ldst_op)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
        && Assembler::inv_rs1(x) == G0
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
        && Assembler::inv_rd(x) == O7;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
  bool is_ic_miss_trap();       // Inline-cache uses a trap to detect a miss
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
  bool is_return() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
    // is it the output of MacroAssembler::ret or MacroAssembler::retl?
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
    const int pc_return_offset = 8; // see frame_sparc.hpp
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
    return is_op3(x, Assembler::jmpl_op3, Assembler::arith_op)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
        && (inv_rs1(x) == I7 || inv_rs1(x) == O7)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
        && inv_immed(x) && inv_simm(x, 13) == pc_return_offset
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
        && inv_rd(x) == G0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  bool is_int_jump() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
    // is it the output of MacroAssembler::b?
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
    return is_op2(x, Assembler::bp_op2) || is_op2(x, Assembler::br_op2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
  bool is_float_jump() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
    // is it the output of MacroAssembler::fb?
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
    return is_op2(x, Assembler::fbp_op2) || is_op2(x, Assembler::fb_op2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
  bool is_jump() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
    return is_int_jump() || is_float_jump();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  bool is_cond_jump() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
    return (is_int_jump() && Assembler::inv_cond(x) != Assembler::always) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
           (is_float_jump() && Assembler::inv_cond(x) != Assembler::f_always);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  bool is_stack_bang() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
    return is_op3(x, Assembler::stw_op3, Assembler::ldst_op) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
      (inv_rd(x) == G0) && (inv_rs1(x) == SP) && (inv_rs2(x) == G3_scratch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  bool is_prefetch() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
    return is_op3(x, Assembler::prefetch_op3, Assembler::ldst_op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
  bool is_membar() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
    return is_op3(x, Assembler::membar_op3, Assembler::arith_op) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
      (inv_rd(x) == G0) && (inv_rs1(x) == O7);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
  bool is_safepoint_poll() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
    return is_op3(x, Assembler::ldx_op3,  Assembler::ldst_op) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
    return is_op3(x, Assembler::lduw_op3, Assembler::ldst_op) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
      (inv_rd(x) == G0) && (inv_immed(x) ? Assembler::inv_simm13(x) == 0 : inv_rs2(x) == G0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
  bool is_zero_test(Register &reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
  bool is_load_store_with_small_offset(Register reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
  static int rdpc_instruction()        { return Assembler::op(Assembler::arith_op ) | Assembler::op3(Assembler::rdreg_op3) | Assembler::u_field(5, 18, 14) | Assembler::rd(O7); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  // Temporary fix: in optimized mode, u_field is a macro for efficiency reasons (see Assembler::u_field) - needs to be fixed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  static int rdpc_instruction()        { return Assembler::op(Assembler::arith_op ) | Assembler::op3(Assembler::rdreg_op3) |            u_field(5, 18, 14) | Assembler::rd(O7); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
  static int nop_instruction()         { return Assembler::op(Assembler::branch_op) | Assembler::op2(Assembler::sethi_op2); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
  static int illegal_instruction();    // the output of __ breakpoint_trap()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
  static int call_instruction(address destination, address pc) { return Assembler::op(Assembler::call_op) | Assembler::wdisp((intptr_t)destination, (intptr_t)pc, 30); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
  static int branch_instruction(Assembler::op2s op2val, Assembler::Condition c, bool a) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
    return Assembler::op(Assembler::branch_op) | Assembler::op2(op2val) | Assembler::annul(a) | Assembler::cond(c);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
  static int op3_instruction(Assembler::ops opval, Register rd, Assembler::op3s op3val, Register rs1, int simm13a) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
    return Assembler::op(opval) | Assembler::rd(rd) | Assembler::op3(op3val) | Assembler::rs1(rs1) | Assembler::immed(true) | Assembler::simm(simm13a, 13);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
  static int sethi_instruction(Register rd, int imm22a) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
    return Assembler::op(Assembler::branch_op) | Assembler::rd(rd) | Assembler::op2(Assembler::sethi_op2) | Assembler::hi22(imm22a);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
 protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
  address  addr_at(int offset) const    { return address(this) + offset; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
  int      long_at(int offset) const    { return *(int*)addr_at(offset); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  void set_long_at(int offset, int i);      /* deals with I-cache */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
  void set_jlong_at(int offset, jlong i);   /* deals with I-cache */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  void set_addr_at(int offset, address x);  /* deals with I-cache */
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
  address instruction_address() const       { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
  address next_instruction_address() const  { return addr_at(BytesPerInstWord); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  static bool is_op( int x, Assembler::ops opval)  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
    return Assembler::inv_op(x) == opval;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
  static bool is_op2(int x, Assembler::op2s op2val) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
    return Assembler::inv_op(x) == Assembler::branch_op && Assembler::inv_op2(x) == op2val;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
  static bool is_op3(int x, Assembler::op3s op3val, Assembler::ops opval) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
    return Assembler::inv_op(x) == opval && Assembler::inv_op3(x) == op3val;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
  // utilities to help subclasses decode:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
  static Register inv_rd(  int x ) { return Assembler::inv_rd( x); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
  static Register inv_rs1( int x ) { return Assembler::inv_rs1(x); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
  static Register inv_rs2( int x ) { return Assembler::inv_rs2(x); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
  static bool inv_immed( int x ) { return Assembler::inv_immed(x); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  static bool inv_annul( int x ) { return (Assembler::annul(true) & x) != 0; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
  static int  inv_cond(  int x ) { return Assembler::inv_cond(x); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
  static int inv_op(  int x ) { return Assembler::inv_op( x); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
  static int inv_op2( int x ) { return Assembler::inv_op2(x); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  static int inv_op3( int x ) { return Assembler::inv_op3(x); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  static int inv_simm(    int x, int nbits ) { return Assembler::inv_simm(x, nbits); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
  static intptr_t inv_wdisp(   int x, int nbits ) { return Assembler::inv_wdisp(  x, 0, nbits); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
  static intptr_t inv_wdisp16( int x )            { return Assembler::inv_wdisp16(x, 0); }
14631
526804361522 8003250: SPARC: move MacroAssembler into separate file
twisti
parents: 13728
diff changeset
   196
  static int branch_destination_offset(int x) { return MacroAssembler::branch_destination(x, 0); }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
  static int patch_branch_destination_offset(int dest_offset, int x) {
14631
526804361522 8003250: SPARC: move MacroAssembler into separate file
twisti
parents: 13728
diff changeset
   198
    return MacroAssembler::patched_branch(dest_offset, x, 0);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
  // utility for checking if x is either of 2 small constants
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
  static bool is_either(int x, int k1, int k2) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
    // return x == k1 || x == k2;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
    return (1 << x) & (1 << k1 | 1 << k2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
  // utility for checking overflow of signed instruction fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
  static bool fits_in_simm(int x, int nbits) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
    // cf. Assembler::assert_signed_range()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
    // return -(1 << nbits-1) <= x  &&  x < ( 1 << nbits-1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
    return (unsigned)(x + (1 << nbits-1)) < (unsigned)(1 << nbits);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
  // set a signed immediate field
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
  static int set_simm(int insn, int imm, int nbits) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
    return (insn &~ Assembler::simm(-1, nbits)) | Assembler::simm(imm, nbits);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
  // set a wdisp field (disp should be the difference of two addresses)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
  static int set_wdisp(int insn, intptr_t disp, int nbits) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
    return (insn &~ Assembler::wdisp((intptr_t)-4, (intptr_t)0, nbits)) | Assembler::wdisp(disp, 0, nbits);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
  static int set_wdisp16(int insn, intptr_t disp) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
    return (insn &~ Assembler::wdisp16((intptr_t)-4, 0)) | Assembler::wdisp16(disp, 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
  // get a simm13 field from an arithmetic or memory instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
  static int get_simm13(int insn) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
    assert(is_either(Assembler::inv_op(insn),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
                     Assembler::arith_op, Assembler::ldst_op) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
            (insn & Assembler::immed(true)), "must have a simm13 field");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
    return Assembler::inv_simm(insn, 13);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
  // set the simm13 field of an arithmetic or memory instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  static bool set_simm13(int insn, int imm) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
    get_simm13(insn);           // tickle the assertion check
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
    return set_simm(insn, imm, 13);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
  // combine the fields of a sethi stream (7 instructions ) and an add, jmp or ld/st
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
  static intptr_t data64( address pc, int arith_insn ) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
    assert(is_op2(*(unsigned int *)pc, Assembler::sethi_op2), "must be sethi");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
    intptr_t hi = (intptr_t)gethi( (unsigned int *)pc );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
    intptr_t lo = (intptr_t)get_simm13(arith_insn);
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8921
diff changeset
   247
    assert((unsigned)lo < (1 << 10), "offset field of set_metadata must be 10 bits");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
    return hi | lo;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
  // Regenerate the instruction sequence that performs the 64 bit
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
  // sethi.  This only does the sethi.  The disp field (bottom 10 bits)
2131
98f9cef66a34 6810672: Comment typos
twisti
parents: 670
diff changeset
   253
  // must be handled separately.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
  static void set_data64_sethi(address instaddr, intptr_t x);
8724
693c6b883b54 7028374: race in fix_oop_relocations for scavengeable nmethods
never
parents: 7397
diff changeset
   255
  static void verify_data64_sethi(address instaddr, intptr_t x);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
  // combine the fields of a sethi/simm13 pair (simm13 = or, add, jmpl, ld/st)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
  static int data32(int sethi_insn, int arith_insn) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
    assert(is_op2(sethi_insn, Assembler::sethi_op2), "must be sethi");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
    int hi = Assembler::inv_hi22(sethi_insn);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
    int lo = get_simm13(arith_insn);
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8921
diff changeset
   262
    assert((unsigned)lo < (1 << 10), "offset field of set_metadata must be 10 bits");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
    return hi | lo;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
  static int set_data32_sethi(int sethi_insn, int imm) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
    // note that Assembler::hi22 clips the low 10 bits for us
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
    assert(is_op2(sethi_insn, Assembler::sethi_op2), "must be sethi");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
    return (sethi_insn &~ Assembler::hi22(-1)) | Assembler::hi22(imm);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
  static int set_data32_simm13(int arith_insn, int imm) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
    get_simm13(arith_insn);             // tickle the assertion check
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
    int imm10 = Assembler::low10(imm);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
    return (arith_insn &~ Assembler::simm(-1, 13)) | Assembler::simm(imm10, 13);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
  static int low10(int imm) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
    return Assembler::low10(imm);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
  // Perform the inverse of the LP64 Macroassembler::sethi
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
  // routine.  Extracts the 54 bits of address from the instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
  // stream. This routine must agree with the sethi routine in
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
  // assembler_inline_sparc.hpp
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
  static address gethi( unsigned int *pc ) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
    int i = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
    uintptr_t adr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
    // We first start out with the real sethi instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
    assert(is_op2(*pc, Assembler::sethi_op2), "in gethi - must be sethi");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
    adr = (unsigned int)Assembler::inv_hi22( *(pc++) );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
    i++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
    while ( i < 7 ) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
       // We're done if we hit a nop
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
       if ( (int)*pc == nop_instruction() ) break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
       assert ( Assembler::inv_op(*pc) == Assembler::arith_op, "in gethi - must be arith_op" );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
       switch  ( Assembler::inv_op3(*pc) ) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
         case Assembler::xor_op3:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
           adr ^= (intptr_t)get_simm13( *pc );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
           return ( (address)adr );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
           break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
         case Assembler::sll_op3:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
           adr <<= ( *pc & 0x3f );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
           break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
         case Assembler::or_op3:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
           adr |= (intptr_t)get_simm13( *pc );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
           break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
         default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
           assert ( 0, "in gethi - Should not reach here" );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
           break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
       }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
       pc++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
       i++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
    return ( (address)adr );
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
  void  verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
  void  print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
  // unit test stuff
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
  static void test() {}                 // override for testing
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
  inline friend NativeInstruction* nativeInstruction_at(address address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
inline NativeInstruction* nativeInstruction_at(address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
    NativeInstruction* inst = (NativeInstruction*)address;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
      inst->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
    return inst;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
//-----------------------------------------------------------------------------
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
// The NativeCall is an abstraction for accessing/manipulating native call imm32 instructions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
// (used to manipulate inline caches, primitive & dll calls, etc.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
inline NativeCall* nativeCall_at(address instr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
inline NativeCall* nativeCall_overwriting_at(address instr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
                                             address destination);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
inline NativeCall* nativeCall_before(address return_address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
class NativeCall: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
    instruction_size                   = 8,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
    return_address_offset              = 8,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
    call_displacement_width            = 30,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
    displacement_offset                = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
    instruction_offset                 = 0
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
  address instruction_address() const       { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
  address next_instruction_address() const  { return addr_at(instruction_size); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
  address return_address() const            { return addr_at(return_address_offset); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
  address destination() const               { return inv_wdisp(long_at(0), call_displacement_width) + instruction_address(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
  address displacement_address() const      { return addr_at(displacement_offset); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
  void  set_destination(address dest)       { set_long_at(0, set_wdisp(long_at(0), dest - instruction_address(), call_displacement_width)); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
  void  set_destination_mt_safe(address dest);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
  void  verify_alignment() {} // do nothing on sparc
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
  void  verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
  void  print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
  // unit test stuff
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
  static void  test();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
  // Creation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
  friend inline NativeCall* nativeCall_at(address instr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
  friend NativeCall* nativeCall_overwriting_at(address instr, address destination = NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
    // insert a "blank" call:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
    NativeCall* call = (NativeCall*)instr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
    call->set_long_at(0 * BytesPerInstWord, call_instruction(destination, instr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
    call->set_long_at(1 * BytesPerInstWord, nop_instruction());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
    assert(call->addr_at(2 * BytesPerInstWord) - instr == instruction_size, "instruction size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
    // check its structure now:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
    assert(nativeCall_at(instr)->destination() == destination, "correct call destination");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
    return call;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
  friend inline NativeCall* nativeCall_before(address return_address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
    NativeCall* call = (NativeCall*)(return_address - return_address_offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
      call->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
    return call;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
  static bool is_call_at(address instr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
    return nativeInstruction_at(instr)->is_call();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
  static bool is_call_before(address instr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
    return nativeInstruction_at(instr - return_address_offset)->is_call();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
  static bool is_call_to(address instr, address target) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
    return nativeInstruction_at(instr)->is_call() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
      nativeCall_at(instr)->destination() == target;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
  // MT-safe patching of a call instruction.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
  static void insert(address code_pos, address entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
    (void)nativeCall_overwriting_at(code_pos, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
  static void replace_mt_safe(address instr_addr, address code_buffer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
inline NativeCall* nativeCall_at(address instr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
  NativeCall* call = (NativeCall*)instr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
  call->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
  return call;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
// The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
// instructions in the sparcv9 vm.  Used to call native methods which may be loaded
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
// anywhere in the address space, possibly out of reach of a call instruction.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
#ifndef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
// On 32-bit systems, a far call is the same as a near one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
class NativeFarCall;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
inline NativeFarCall* nativeFarCall_at(address instr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
class NativeFarCall : public NativeCall {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
  friend inline NativeFarCall* nativeFarCall_at(address instr) { return (NativeFarCall*)nativeCall_at(instr); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
  friend NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
                                                        { return (NativeFarCall*)nativeCall_overwriting_at(instr, destination); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
  friend NativeFarCall* nativeFarCall_before(address return_address)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
                                                        { return (NativeFarCall*)nativeCall_before(return_address); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
// The format of this extended-range call is:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
//      jumpl_to addr, lreg
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
//      == sethi %hi54(addr), O7 ;  jumpl O7, %lo10(addr), O7 ;  <delay>
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
// That is, it is essentially the same as a NativeJump.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
class NativeFarCall;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
inline NativeFarCall* nativeFarCall_at(address instr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
class NativeFarCall: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
    // instruction_size includes the delay slot instruction.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
    instruction_size                   = 9 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
    return_address_offset              = 9 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
    jmpl_offset                        = 7 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
    displacement_offset                = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
    instruction_offset                 = 0
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
  address instruction_address() const       { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
  address next_instruction_address() const  { return addr_at(instruction_size); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
  address return_address() const            { return addr_at(return_address_offset); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
  address destination() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
    return (address) data64(addr_at(0), long_at(jmpl_offset));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
  address displacement_address() const      { return addr_at(displacement_offset); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
  void set_destination(address dest);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
  bool destination_is_compiled_verified_entry_point();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
  void  verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
  void  print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
  // unit test stuff
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
  static void  test();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
  // Creation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
  friend inline NativeFarCall* nativeFarCall_at(address instr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
    NativeFarCall* call = (NativeFarCall*)instr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
      call->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
    return call;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
  friend inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
    Unimplemented();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
    NativeFarCall* call = (NativeFarCall*)instr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
    return call;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
  friend NativeFarCall* nativeFarCall_before(address return_address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
    NativeFarCall* call = (NativeFarCall*)(return_address - return_address_offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
      call->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
    return call;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
  static bool is_call_at(address instr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
  // MT-safe patching of a call instruction.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
  static void insert(address code_pos, address entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
    (void)nativeFarCall_overwriting_at(code_pos, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
  static void replace_mt_safe(address instr_addr, address code_buffer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
#endif // _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8921
diff changeset
   509
// An interface for accessing/manipulating native set_metadata imm, reg instructions.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
// (used to manipulate inlined data references, etc.)
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8921
diff changeset
   511
//      set_metadata imm, reg
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
//      == sethi %hi22(imm), reg ;  add reg, %lo10(imm), reg
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
class NativeMovConstReg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
inline NativeMovConstReg* nativeMovConstReg_at(address address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
class NativeMovConstReg: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
    sethi_offset           = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
    add_offset             = 7 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
    instruction_size       = 8 * BytesPerInstWord
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
    add_offset             = 4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
    instruction_size       = 8
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
  address instruction_address() const       { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
  address next_instruction_address() const  { return addr_at(instruction_size); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
  // (The [set_]data accessor respects oop_type relocs also.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
  intptr_t data() const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
  void set_data(intptr_t x);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
  // report the destination register
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
  Register destination() { return inv_rd(long_at(sethi_offset)); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
  void  verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
  void  print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
  // unit test stuff
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
  static void test();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
  // Creation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
  friend inline NativeMovConstReg* nativeMovConstReg_at(address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
    NativeMovConstReg* test = (NativeMovConstReg*)address;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
      test->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
    return test;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
  friend NativeMovConstReg* nativeMovConstReg_before(address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
    NativeMovConstReg* test = (NativeMovConstReg*)(address - instruction_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
      test->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
    return test;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8921
diff changeset
   565
// An interface for accessing/manipulating native set_metadata imm, reg instructions.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
// (used to manipulate inlined data references, etc.)
13728
882756847a04 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 8921
diff changeset
   567
//      set_metadata imm, reg
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
//      == sethi %hi22(imm), reg; nop; add reg, %lo10(imm), reg
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
// Note that it is identical to NativeMovConstReg with the exception of a nop between the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
// sethi and the add.  The nop is required to be in the delay slot of the call instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
// which overwrites the sethi during patching.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
class NativeMovConstRegPatching;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address);class NativeMovConstRegPatching: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
    sethi_offset           = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
    nop_offset             = 7 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
    nop_offset             = sethi_offset + BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
    add_offset             = nop_offset   + BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
    instruction_size       = add_offset   + BytesPerInstWord
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
  address instruction_address() const       { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
  address next_instruction_address() const  { return addr_at(instruction_size); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
  // (The [set_]data accessor respects oop_type relocs also.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
  int data() const;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
  void  set_data(int x);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
  // report the destination register
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
  Register destination() { return inv_rd(long_at(sethi_offset)); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
  void  verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
  void  print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
  // unit test stuff
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
  static void test();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
  // Creation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
  friend inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
    NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)address;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
      test->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
    return test;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
  friend NativeMovConstRegPatching* nativeMovConstRegPatching_before(address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
    NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
      test->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
    return test;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
// An interface for accessing/manipulating native memory ops
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
//      ld* [reg + offset], reg
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
//      st* reg, [reg + offset]
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
//      sethi %hi(imm), reg; add reg, %lo(imm), reg; ld* [reg1 + reg], reg2
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
//      sethi %hi(imm), reg; add reg, %lo(imm), reg; st* reg2, [reg1 + reg]
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
// Ops covered: {lds,ldu,st}{w,b,h}, {ld,st}{d,x}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
class NativeMovRegMem;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
inline NativeMovRegMem* nativeMovRegMem_at (address address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
class NativeMovRegMem: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
    op3_mask_ld = 1 << Assembler::lduw_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
                  1 << Assembler::ldub_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
                  1 << Assembler::lduh_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   639
                  1 << Assembler::ldd_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
                  1 << Assembler::ldsw_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
                  1 << Assembler::ldsb_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
                  1 << Assembler::ldsh_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
                  1 << Assembler::ldx_op3,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
    op3_mask_st = 1 << Assembler::stw_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
                  1 << Assembler::stb_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
                  1 << Assembler::sth_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
                  1 << Assembler::std_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
                  1 << Assembler::stx_op3,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
    op3_ldst_int_limit = Assembler::ldf_op3,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   650
    op3_mask_ldf = 1 << (Assembler::ldf_op3  - op3_ldst_int_limit) |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   651
                   1 << (Assembler::lddf_op3 - op3_ldst_int_limit),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   652
    op3_mask_stf = 1 << (Assembler::stf_op3  - op3_ldst_int_limit) |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
                   1 << (Assembler::stdf_op3 - op3_ldst_int_limit),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
    offset_width    = 13,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
    sethi_offset    = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
    add_offset      = 7 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
    add_offset      = 4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
    ldst_offset     = add_offset + BytesPerInstWord
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
  bool is_immediate() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
    // check if instruction is ld* [reg + offset], reg or st* reg, [reg + offset]
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
    int i0 = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
    return (is_op(i0, Assembler::ldst_op));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
  address instruction_address() const           { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
  address next_instruction_address() const      {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   673
    return addr_at(is_immediate() ? 4 : (7 * BytesPerInstWord));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   674
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   675
    return addr_at(is_immediate() ? 4 : 12);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   677
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
  intptr_t   offset() const                             {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
     return is_immediate()? inv_simm(long_at(0), offset_width) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
                            nativeMovConstReg_at(addr_at(0))->data();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
  void  set_offset(intptr_t x) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
    if (is_immediate()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
      guarantee(fits_in_simm(x, offset_width), "data block offset overflow");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
      set_long_at(0, set_simm(long_at(0), x, offset_width));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
    } else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
      nativeMovConstReg_at(addr_at(0))->set_data(x);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
489c9b5090e2 Initial load
duke
parents:
diff changeset
   690
  void  add_offset_in_bytes(intptr_t radd_offset)     {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
      set_offset (offset() + radd_offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
  void  copy_instruction_to(address new_instruction_address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
  void verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
  void print ();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
  // unit test stuff
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
  static void test();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
  friend inline NativeMovRegMem* nativeMovRegMem_at (address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
    NativeMovRegMem* test = (NativeMovRegMem*)address;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
      test->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
    return test;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
// An interface for accessing/manipulating native memory ops
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
//      ld* [reg + offset], reg
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
//      st* reg, [reg + offset]
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
//      sethi %hi(imm), reg; nop; add reg, %lo(imm), reg; ld* [reg1 + reg], reg2
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
//      sethi %hi(imm), reg; nop; add reg, %lo(imm), reg; st* reg2, [reg1 + reg]
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
// Ops covered: {lds,ldu,st}{w,b,h}, {ld,st}{d,x}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
// Note that it is identical to NativeMovRegMem with the exception of a nop between the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
// sethi and the add.  The nop is required to be in the delay slot of the call instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
// which overwrites the sethi during patching.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
class NativeMovRegMemPatching;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   724
inline NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
class NativeMovRegMemPatching: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
    op3_mask_ld = 1 << Assembler::lduw_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
                  1 << Assembler::ldub_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   730
                  1 << Assembler::lduh_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
                  1 << Assembler::ldd_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
                  1 << Assembler::ldsw_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
                  1 << Assembler::ldsb_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
                  1 << Assembler::ldsh_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
                  1 << Assembler::ldx_op3,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
    op3_mask_st = 1 << Assembler::stw_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
                  1 << Assembler::stb_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
                  1 << Assembler::sth_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
                  1 << Assembler::std_op3 |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
                  1 << Assembler::stx_op3,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
    op3_ldst_int_limit = Assembler::ldf_op3,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
    op3_mask_ldf = 1 << (Assembler::ldf_op3  - op3_ldst_int_limit) |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
                   1 << (Assembler::lddf_op3 - op3_ldst_int_limit),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
    op3_mask_stf = 1 << (Assembler::stf_op3  - op3_ldst_int_limit) |
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
                   1 << (Assembler::stdf_op3 - op3_ldst_int_limit),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
    offset_width    = 13,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
    sethi_offset    = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
    nop_offset      = 7 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
    nop_offset      = 4,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
    add_offset      = nop_offset + BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
    ldst_offset     = add_offset + BytesPerInstWord
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
  bool is_immediate() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
    // check if instruction is ld* [reg + offset], reg or st* reg, [reg + offset]
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
    int i0 = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
    return (is_op(i0, Assembler::ldst_op));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   762
489c9b5090e2 Initial load
duke
parents:
diff changeset
   763
  address instruction_address() const           { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
  address next_instruction_address() const      {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
    return addr_at(is_immediate()? 4 : 16);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   767
  int   offset() const                          {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
     return is_immediate()? inv_simm(long_at(0), offset_width) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
                            nativeMovConstRegPatching_at(addr_at(0))->data();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
  void  set_offset(int x) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
    if (is_immediate()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
      guarantee(fits_in_simm(x, offset_width), "data block offset overflow");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
      set_long_at(0, set_simm(long_at(0), x, offset_width));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   776
    else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   777
      nativeMovConstRegPatching_at(addr_at(0))->set_data(x);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   779
489c9b5090e2 Initial load
duke
parents:
diff changeset
   780
  void  add_offset_in_bytes(intptr_t radd_offset)     {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
      set_offset (offset() + radd_offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
  void  copy_instruction_to(address new_instruction_address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   785
489c9b5090e2 Initial load
duke
parents:
diff changeset
   786
  void verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
  void print ();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
  // unit test stuff
489c9b5090e2 Initial load
duke
parents:
diff changeset
   790
  static void test();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   791
489c9b5090e2 Initial load
duke
parents:
diff changeset
   792
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   793
  friend inline NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   794
    NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)address;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   795
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   796
      test->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   797
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   798
    return test;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   799
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   800
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   801
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
// An interface for accessing/manipulating native jumps
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
//      jump_to addr
489c9b5090e2 Initial load
duke
parents:
diff changeset
   805
//      == sethi %hi22(addr), temp ;  jumpl reg, %lo10(addr), G0 ;  <delay>
489c9b5090e2 Initial load
duke
parents:
diff changeset
   806
//      jumpl_to addr, lreg
489c9b5090e2 Initial load
duke
parents:
diff changeset
   807
//      == sethi %hi22(addr), temp ;  jumpl reg, %lo10(addr), lreg ;  <delay>
489c9b5090e2 Initial load
duke
parents:
diff changeset
   808
class NativeJump;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   809
inline NativeJump* nativeJump_at(address address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   810
class NativeJump: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   811
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   812
  void guarantee_displacement(int disp, int width) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   813
    guarantee(fits_in_simm(disp, width + 2), "branch displacement overflow");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   814
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   815
489c9b5090e2 Initial load
duke
parents:
diff changeset
   816
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   817
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   818
    sethi_offset           = 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   819
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   820
    jmpl_offset            = 7 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   821
    instruction_size       = 9 * BytesPerInstWord  // includes delay slot
489c9b5090e2 Initial load
duke
parents:
diff changeset
   822
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   823
    jmpl_offset            = 1 * BytesPerInstWord,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   824
    instruction_size       = 3 * BytesPerInstWord  // includes delay slot
489c9b5090e2 Initial load
duke
parents:
diff changeset
   825
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   826
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   827
489c9b5090e2 Initial load
duke
parents:
diff changeset
   828
  address instruction_address() const       { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
  address next_instruction_address() const  { return addr_at(instruction_size); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
489c9b5090e2 Initial load
duke
parents:
diff changeset
   831
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
  address jump_destination() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
    return (address) data64(instruction_address(), long_at(jmpl_offset));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
  void set_jump_destination(address dest) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
    set_data64_sethi( instruction_address(), (intptr_t)dest);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
    set_long_at(jmpl_offset,  set_data32_simm13( long_at(jmpl_offset),  (intptr_t)dest));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   838
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
  address jump_destination() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   841
    return (address) data32(long_at(sethi_offset), long_at(jmpl_offset));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
  void set_jump_destination(address dest) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   844
    set_long_at(sethi_offset, set_data32_sethi(  long_at(sethi_offset), (intptr_t)dest));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
    set_long_at(jmpl_offset,  set_data32_simm13( long_at(jmpl_offset),  (intptr_t)dest));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   848
489c9b5090e2 Initial load
duke
parents:
diff changeset
   849
  // Creation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
  friend inline NativeJump* nativeJump_at(address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   851
    NativeJump* jump = (NativeJump*)address;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
    #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   853
      jump->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   854
    #endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   855
    return jump;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
489c9b5090e2 Initial load
duke
parents:
diff changeset
   858
  void verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
  void print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
  // Unit testing stuff
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
  static void test();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
  // Insertion of native jump instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
  static void insert(address code_pos, address entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
  // MT-safe insertion of native jump at verified method entry
489c9b5090e2 Initial load
duke
parents:
diff changeset
   867
  static void check_verified_entry_alignment(address entry, address verified_entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   868
    // nothing to do for sparc.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   870
  static void patch_verified_entry(address entry, address verified_entry, address dest);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   871
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
// Despite the name, handles only simple branches.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   876
class NativeGeneralJump;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   877
inline NativeGeneralJump* nativeGeneralJump_at(address address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
class NativeGeneralJump: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   881
    instruction_size                   = 8
489c9b5090e2 Initial load
duke
parents:
diff changeset
   882
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   883
489c9b5090e2 Initial load
duke
parents:
diff changeset
   884
  address instruction_address() const       { return addr_at(0); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   885
  address jump_destination()    const       { return addr_at(0) + branch_destination_offset(long_at(0)); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   886
  void set_jump_destination(address dest) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   887
    int patched_instr = patch_branch_destination_offset(dest - addr_at(0), long_at(0));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   888
    set_long_at(0, patched_instr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   889
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   890
  NativeInstruction *delay_slot_instr() { return nativeInstruction_at(addr_at(4));}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   891
  void fill_delay_slot(int instr) { set_long_at(4, instr);}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   892
  Assembler::Condition condition() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
    int x = long_at(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
    return (Assembler::Condition) Assembler::inv_cond(x);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
  // Creation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
  friend inline NativeGeneralJump* nativeGeneralJump_at(address address) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
    NativeGeneralJump* jump = (NativeGeneralJump*)(address);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
      jump->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
    return jump;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
  // Insertion of native general jump instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
  static void insert_unconditional(address code_pos, address entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
  static void replace_mt_safe(address instr_addr, address code_buffer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
  void verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
489c9b5090e2 Initial load
duke
parents:
diff changeset
   913
489c9b5090e2 Initial load
duke
parents:
diff changeset
   914
class NativeIllegalInstruction: public NativeInstruction {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   915
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   916
  enum Sparc_specific_constants {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   917
    instruction_size            =    4
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
489c9b5090e2 Initial load
duke
parents:
diff changeset
   920
  // Insert illegal opcode as specific address
489c9b5090e2 Initial load
duke
parents:
diff changeset
   921
  static void insert(address code_pos);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   922
};
7397
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
   923
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 5547
diff changeset
   924
#endif // CPU_SPARC_VM_NATIVEINST_SPARC_HPP