blob: 87ea7f5e56fb9ad82dc58014265f6acd7cf3bb71 [file] [log] [blame]
/*
* 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