src/hotspot/cpu/arm/register_arm.hpp
author bchristi
Wed, 13 Dec 2017 11:43:57 -0800
changeset 48293 2fa0077c4fec
parent 47216 71c04702a3d5
child 52351 0ecb4e520110
permissions -rw-r--r--
8193460: Take tools/launcher/TestXcheckJNIWarnings.java back off the ProblemList Reviewed-by: mchung, psandoz

/*
 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef CPU_ARM_VM_REGISTER_ARM_HPP
#define CPU_ARM_VM_REGISTER_ARM_HPP

#include "asm/register.hpp"
#include "vm_version_arm.hpp"

class VMRegImpl;
typedef VMRegImpl* VMReg;

// These are declared ucontext.h
#undef R0
#undef R1
#undef R2
#undef R3
#undef R4
#undef R5
#undef R6
#undef R7
#undef R8
#undef R9
#undef R10
#undef R11
#undef R12
#undef R13
#undef R14
#undef R15

#define R(r)   ((Register)(r))

/////////////////////////////////
// Support for different ARM ABIs
// Note: default ABI is for linux


// R9_IS_SCRATCHED
//
// The ARM ABI does not guarantee that R9 is callee saved.
// Set R9_IS_SCRATCHED to 1 to ensure it is properly saved/restored by
// the caller.
#ifndef R9_IS_SCRATCHED
// Default: R9 is callee saved
#define R9_IS_SCRATCHED 0
#endif

#ifndef AARCH64
// FP_REG_NUM
//
// The ARM ABI does not state which register is used for the frame pointer.
// Note: for the ABIs we are currently aware of, FP is currently
// either R7 or R11. Code may have to be extended if a third register
// register must be supported (see altFP_7_11).
#ifndef FP_REG_NUM
// Default: FP is R11
#define FP_REG_NUM 11
#endif
#endif // AARCH64

// ALIGN_WIDE_ARGUMENTS
//
// The ARM ABI requires 64-bits arguments to be aligned on 4 words
// or on even registers. Set ALIGN_WIDE_ARGUMENTS to 1 for that behavior.
//
// Unfortunately, some platforms do not endorse that part of the ABI.
//
// We are aware of one which expects 64-bit arguments to only be 4
// bytes aligned and can for instance use R3 + a stack slot for such
// an argument.
//
// This is the behavor implemented if (ALIGN_WIDE_ARGUMENTS == 0)
#ifndef  ALIGN_WIDE_ARGUMENTS
// Default: align on 8 bytes and avoid using <r3+stack>
#define ALIGN_WIDE_ARGUMENTS 1
#endif

#define R0     ((Register)0)
#define R1     ((Register)1)
#define R2     ((Register)2)
#define R3     ((Register)3)
#define R4     ((Register)4)
#define R5     ((Register)5)
#define R6     ((Register)6)
#define R7     ((Register)7)
#define R8     ((Register)8)
#define R9     ((Register)9)
#define R10    ((Register)10)
#define R11    ((Register)11)
#define R12    ((Register)12)
#define R13    ((Register)13)
#define R14    ((Register)14)
#define R15    ((Register)15)

#ifdef AARCH64

#define R16    ((Register)16)
#define R17    ((Register)17)
#define R18    ((Register)18)
#define R19    ((Register)19)
#define R20    ((Register)20)
#define R21    ((Register)21)
#define R22    ((Register)22)
#define R23    ((Register)23)
#define R24    ((Register)24)
#define R25    ((Register)25)
#define R26    ((Register)26)
#define R27    ((Register)27)
#define R28    ((Register)28)
#define R29    ((Register)29)
#define R30    ((Register)30)
#define ZR     ((Register)31)
#define SP     ((Register)32)

#define FP     R29
#define LR     R30

#define altFP_7_11 R7

#else // !AARCH64

#define FP     ((Register)FP_REG_NUM)

// Safe use of registers which may be FP on some platforms.
//
// altFP_7_11: R7 if not equal to FP, else R11 (the default FP)
//
// Note: add additional altFP_#_11 for each register potentially used
// as FP on supported ABIs (and replace R# by altFP_#_11). altFP_#_11
// must be #define to R11 if and only if # is FP_REG_NUM.
#if (FP_REG_NUM == 7)
#define altFP_7_11     ((Register)11)
#else
#define altFP_7_11     ((Register)7)
#endif
#define SP     R13
#define LR     R14
#define PC     R15

#endif // !AARCH64


class RegisterImpl;
typedef RegisterImpl* Register;

inline Register as_Register(int encoding) {
  return (Register)(intptr_t)encoding;
}

class RegisterImpl : public AbstractRegisterImpl {
 public:
  enum {
#ifdef AARCH64
    number_of_gprs = 31,
    zr_sp_encoding = 31,
#endif
    number_of_registers = AARCH64_ONLY(number_of_gprs + 2) NOT_AARCH64(16)
  };

  Register successor() const      { return as_Register(encoding() + 1); }

  inline friend Register as_Register(int encoding);

  VMReg as_VMReg();

  // accessors
  int   encoding() const          { assert(is_valid(), "invalid register"); return value(); }
  const char* name() const;

#ifdef AARCH64
  int encoding_with_zr() const   { assert (is_valid_gpr_or_zr(), "invalid register"); return (this == ZR) ? zr_sp_encoding : value(); }
  int encoding_with_sp() const   { assert (is_valid_gpr_or_sp(), "invalid register"); return (this == SP) ? zr_sp_encoding : value(); }
#endif

  // testers
  bool is_valid() const           { return 0 <= value() && value() < number_of_registers; }

#ifdef AARCH64
  bool is_valid_gpr()       const  { return (0 <= value() && value() < number_of_gprs); }
  bool is_valid_gpr_or_zr() const  { return is_valid_gpr() || (this == ZR); }
  bool is_valid_gpr_or_sp() const  { return is_valid_gpr() || (this == SP); }
#endif
};

CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1));


// Use FloatRegister as shortcut
class FloatRegisterImpl;
typedef FloatRegisterImpl* FloatRegister;

inline FloatRegister as_FloatRegister(int encoding) {
  return (FloatRegister)(intptr_t)encoding;
}

class FloatRegisterImpl : public AbstractRegisterImpl {
 public:
  enum {
#ifdef AARCH64
    number_of_registers = 32
#else
    number_of_registers = NOT_COMPILER2(32) COMPILER2_PRESENT(64)
#endif
  };

  inline friend FloatRegister as_FloatRegister(int encoding);

  VMReg as_VMReg();

  int   encoding() const          { assert(is_valid(), "invalid register"); return value(); }
  bool  is_valid() const          { return 0 <= (intx)this && (intx)this < number_of_registers; }
  FloatRegister successor() const { return as_FloatRegister(encoding() + 1); }

  const char* name() const;

#ifndef AARCH64
  int hi_bits() const {
    return (encoding() >> 1) & 0xf;
  }

  int lo_bit() const {
    return encoding() & 1;
  }

  int hi_bit() const {
    return encoding() >> 5;
  }
#endif // !AARCH64
};

CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg, (-1));

#ifdef AARCH64

CONSTANT_REGISTER_DECLARATION(FloatRegister, V0,     ( 0));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V1,     ( 1));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V2,     ( 2));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V3,     ( 3));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V4,     ( 4));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V5,     ( 5));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V6,     ( 6));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V7,     ( 7));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V8,     ( 8));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V9,     ( 9));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V10,    (10));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V11,    (11));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V12,    (12));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V13,    (13));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V14,    (14));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V15,    (15));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V16,    (16));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V17,    (17));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V18,    (18));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V19,    (19));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V20,    (20));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V21,    (21));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V22,    (22));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V23,    (23));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V24,    (24));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V25,    (25));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V26,    (26));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V27,    (27));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V28,    (28));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V29,    (29));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V30,    (30));
CONSTANT_REGISTER_DECLARATION(FloatRegister, V31,    (31));

#define S0       V0
#define S1_reg   V1
#define Stemp    V31

#define D0       V0
#define D1       V1

#else // AARCH64

/*
 * S1-S6 are named with "_reg" suffix to avoid conflict with
 * constants defined in sharedRuntimeTrig.cpp
 */
CONSTANT_REGISTER_DECLARATION(FloatRegister, S0,     ( 0));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S1_reg, ( 1));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S2_reg, ( 2));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S3_reg, ( 3));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S4_reg, ( 4));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S5_reg, ( 5));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S6_reg, ( 6));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S7,     ( 7));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S8,     ( 8));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S9,     ( 9));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S10,    (10));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S11,    (11));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S12,    (12));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S13,    (13));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S14,    (14));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S15,    (15));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S16,    (16));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S17,    (17));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S18,    (18));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S19,    (19));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S20,    (20));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S21,    (21));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S22,    (22));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S23,    (23));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S24,    (24));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S25,    (25));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S26,    (26));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S27,    (27));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S28,    (28));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S29,    (29));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S30,    (30));
CONSTANT_REGISTER_DECLARATION(FloatRegister, S31,    (31));
CONSTANT_REGISTER_DECLARATION(FloatRegister, Stemp,  (30));

CONSTANT_REGISTER_DECLARATION(FloatRegister, D0,     ( 0));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D1,     ( 2));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D2,     ( 4));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D3,     ( 6));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D4,     ( 8));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D5,     ( 10));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D6,     ( 12));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D7,     ( 14));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D8,     ( 16));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D9,     ( 18));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D10,    ( 20));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D11,    ( 22));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D12,    ( 24));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D13,    ( 26));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D14,    ( 28));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D15,    (30));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D16,    (32));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D17,    (34));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D18,    (36));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D19,    (38));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D20,    (40));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D21,    (42));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D22,    (44));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D23,    (46));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D24,    (48));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D25,    (50));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D26,    (52));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D27,    (54));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D28,    (56));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D29,    (58));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D30,    (60));
CONSTANT_REGISTER_DECLARATION(FloatRegister, D31,    (62));

#endif // AARCH64

class ConcreteRegisterImpl : public AbstractRegisterImpl {
 public:
  enum {
    log_vmregs_per_word = LogBytesPerWord - LogBytesPerInt, // VMRegs are of 4-byte size
#ifdef COMPILER2
    log_bytes_per_fpr  = AARCH64_ONLY(4) NOT_AARCH64(2), // quad vectors
#else
    log_bytes_per_fpr  = AARCH64_ONLY(3) NOT_AARCH64(2), // double vectors
#endif
    log_words_per_fpr  = log_bytes_per_fpr - LogBytesPerWord,
    words_per_fpr      = 1 << log_words_per_fpr,
    log_vmregs_per_fpr = log_bytes_per_fpr - LogBytesPerInt,
    log_vmregs_per_gpr = log_vmregs_per_word,
    vmregs_per_gpr = 1 << log_vmregs_per_gpr,
    vmregs_per_fpr = 1 << log_vmregs_per_fpr,

    num_gpr  = RegisterImpl::number_of_registers << log_vmregs_per_gpr,
    max_gpr0 = num_gpr,
    num_fpr  = FloatRegisterImpl::number_of_registers << log_vmregs_per_fpr,
    max_fpr0 = max_gpr0 + num_fpr,
    number_of_registers = num_gpr + num_fpr +
                          // TODO-AARCH64 revise
                          1+1 // APSR and FPSCR so that c2's REG_COUNT <= ConcreteRegisterImpl::number_of_registers
  };

  static const int max_gpr;
  static const int max_fpr;
};

// TODO-AARCH64 revise the following definitions

class VFPSystemRegisterImpl;
typedef VFPSystemRegisterImpl* VFPSystemRegister;
class VFPSystemRegisterImpl : public AbstractRegisterImpl {
 public:
  int   encoding() const          { return value(); }
};

#define FPSID     ((VFPSystemRegister)0)
#define FPSCR     ((VFPSystemRegister)1)
#define MVFR0     ((VFPSystemRegister)0x6)
#define MVFR1     ((VFPSystemRegister)0x7)

/*
 * Register definitions shared across interpreter and compiler
 */
#define Rexception_obj   AARCH64_ONLY(R19) NOT_AARCH64(R4)
#define Rexception_pc    AARCH64_ONLY(R20) NOT_AARCH64(R5)

#ifdef AARCH64
#define Rheap_base       R27
#endif // AARCH64

/*
 * Interpreter register definitions common to C++ and template interpreters.
 */
#ifdef AARCH64
#define Rlocals          R23
#define Rmethod          R26
#define Rthread          R28
#define Rtemp            R16
#define Rtemp2           R17
#else
#define Rlocals          R8
#define Rmethod          R9
#define Rthread          R10
#define Rtemp            R12
#endif // AARCH64

// Interpreter calling conventions

#define Rparams          AARCH64_ONLY(R8)  NOT_AARCH64(SP)
#define Rsender_sp       AARCH64_ONLY(R19) NOT_AARCH64(R4)

// JSR292
//  Note: R5_mh is needed only during the call setup, including adapters
//  This does not seem to conflict with Rexception_pc
//  In case of issues, R3 might be OK but adapters calling the runtime would have to save it
#define R5_mh            R5 // MethodHandle register, used during the call setup
#define Rmh_SP_save      FP // for C1

/*
 * C++ Interpreter Register Defines
 */
#define Rsave0   R4
#define Rsave1   R5
#define Rsave2   R6
#define Rstate   altFP_7_11 // R7 or R11
#define Ricklass R8

/*
 * TemplateTable Interpreter Register Usage
 */

// Temporary registers
#define R0_tmp                 R0
#define R1_tmp                 R1
#define R2_tmp                 R2
#define R3_tmp                 R3
#define R4_tmp                 R4
#define R5_tmp                 R5
#define R12_tmp                R12
#define LR_tmp                 LR

#define S0_tmp                 S0
#define S1_tmp                 S1_reg

#define D0_tmp                 D0
#define D1_tmp                 D1

// Temporary registers saved across VM calls (according to C calling conventions)
#define Rtmp_save0             AARCH64_ONLY(R19) NOT_AARCH64(R4)
#define Rtmp_save1             AARCH64_ONLY(R20) NOT_AARCH64(R5)

// Cached TOS value
#define R0_tos                 R0

#ifndef AARCH64
#define R0_tos_lo              R0
#define R1_tos_hi              R1
#endif

#define S0_tos                 S0
#define D0_tos                 D0

// Dispatch table
#define RdispatchTable         AARCH64_ONLY(R22) NOT_AARCH64(R6)

// Bytecode pointer
#define Rbcp                   AARCH64_ONLY(R24) NOT_AARCH64(altFP_7_11)

// Pre-loaded next bytecode for the dispatch
#define R3_bytecode            R3

// Conventions between bytecode templates and stubs
#define R2_ClassCastException_obj        R2
#define R4_ArrayIndexOutOfBounds_index   R4

// Interpreter expression stack top
#define Rstack_top             AARCH64_ONLY(R25) NOT_AARCH64(SP)

/*
 * Linux 32-bit ARM C ABI Register calling conventions
 *
 *   REG         use                     callee/caller saved
 *
 *   R0         First argument reg            caller
 *              result register
 *   R1         Second argument reg           caller
 *              result register
 *   R2         Third argument reg            caller
 *   R3         Fourth argument reg           caller
 *
 *   R4 - R8    Local variable registers      callee
 *   R9
 *   R10, R11   Local variable registers      callee
 *
 *   R12 (IP)   Scratch register used in inter-procedural calling
 *   R13 (SP)   Stack Pointer                 callee
 *   R14 (LR)   Link register
 *   R15 (PC)   Program Counter
 *
 * TODO-AARCH64: document AArch64 ABI
 *
 */
#define c_rarg0  R0
#define c_rarg1  R1
#define c_rarg2  R2
#define c_rarg3  R3

#ifdef AARCH64
#define c_rarg4  R4
#define c_rarg5  R5
#define c_rarg6  R6
#define c_rarg7  R7
#endif

#ifdef AARCH64
#define GPR_PARAMS    8
#define FPR_PARAMS    8
#else
#define GPR_PARAMS    4
#endif


// Java ABI
// XXX Is this correct?
#define j_rarg0  c_rarg0
#define j_rarg1  c_rarg1
#define j_rarg2  c_rarg2
#define j_rarg3  c_rarg3

#ifdef AARCH64
#define j_rarg4  c_rarg4
#define j_rarg5  c_rarg5
#define j_rarg6  c_rarg6
#define j_rarg7  c_rarg7
#endif

#endif // CPU_ARM_VM_REGISTER_ARM_HPP