src/hotspot/cpu/arm/register_arm.hpp
author lucy
Mon, 18 Nov 2019 17:11:06 +0100
changeset 59122 5d73255c2d52
parent 53244 9807daeb47c4
permissions -rw-r--r--
8233787: Break cycle in vm_version* includes Reviewed-by: kbarrett, mdoerr

/*
 * Copyright (c) 2008, 2019, 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_REGISTER_ARM_HPP
#define CPU_ARM_REGISTER_ARM_HPP

#include "asm/register.hpp"
#include "runtime/vm_version.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

// 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

// 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)


#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



class RegisterImpl;
typedef RegisterImpl* Register;

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

class RegisterImpl : public AbstractRegisterImpl {
 public:
  enum {
    number_of_registers = 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;


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

};

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 {
    number_of_registers = NOT_COMPILER2(32) COMPILER2_PRESENT(64)
  };

  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;

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

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

  int hi_bit() const {
    return encoding() >> 5;
  }
};

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


/*
 * 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));


class ConcreteRegisterImpl : public AbstractRegisterImpl {
 public:
  enum {
    log_vmregs_per_word = LogBytesPerWord - LogBytesPerInt, // VMRegs are of 4-byte size
#ifdef COMPILER2
    log_bytes_per_fpr  = 2, // quad vectors
#else
    log_bytes_per_fpr  = 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 + 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;
};

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   R4
#define Rexception_pc    R5

/*
 * Interpreter register definitions common to C++ and template interpreters.
 */
#define Rlocals          R8
#define Rmethod          R9
#define Rthread          R10
#define Rtemp            R12

// Interpreter calling conventions

#define Rparams          SP
#define Rsender_sp       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             R4
#define Rtmp_save1             R5

// Cached TOS value
#define R0_tos                 R0

#define R0_tos_lo              R0
#define R1_tos_hi              R1

#define S0_tos                 S0
#define D0_tos                 D0

// Dispatch table
#define RdispatchTable         R6

// Bytecode pointer
#define Rbcp                   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             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
 */
#define c_rarg0  R0
#define c_rarg1  R1
#define c_rarg2  R2
#define c_rarg3  R3


#define GPR_PARAMS    4


// 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


#endif // CPU_ARM_REGISTER_ARM_HPP