blob: 7c9139392fd52d84844057176533c6452aee9881 [file] [edit]
/*
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. 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_RISCV_REGISTER_RISCV_HPP
#define CPU_RISCV_REGISTER_RISCV_HPP
#include "asm/register.hpp"
#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
#define CSR_FFLAGS 0x001 // Floating-Point Accrued Exceptions.
#define CSR_FRM 0x002 // Floating-Point Dynamic Rounding Mode.
#define CSR_FCSR 0x003 // Floating-Point Control and Status Register (frm + fflags).
#define CSR_VSTART 0x008 // Vector start position
#define CSR_VXSAT 0x009 // Fixed-Point Saturate Flag
#define CSR_VXRM 0x00A // Fixed-Point Rounding Mode
#define CSR_VCSR 0x00F // Vector control and status register
#define CSR_VL 0xC20 // Vector length
#define CSR_VTYPE 0xC21 // Vector data type register
#define CSR_VLENB 0xC22 // VLEN/8 (vector register length in bytes)
#define CSR_CYCLE 0xc00 // Cycle counter for RDCYCLE instruction.
#define CSR_TIME 0xc01 // Timer for RDTIME instruction.
#define CSR_INSTRET 0xc02 // Instructions-retired counter for RDINSTRET instruction.
class VMRegImpl;
typedef VMRegImpl* VMReg;
class Register {
private:
int _encoding;
constexpr explicit Register(int encoding) : _encoding(encoding) {}
public:
enum {
number_of_registers = 32,
max_slots_per_register = 2,
// integer registers x8 - x15 and floating-point registers f8 - f15 are allocatable
// for compressed instructions. See Table 17.2 in spec.
compressed_register_base = 8,
compressed_register_top = 15,
};
class RegisterImpl: public AbstractRegisterImpl {
friend class Register;
static constexpr const RegisterImpl* first();
public:
// accessors
constexpr int raw_encoding() const { return checked_cast<int>(this - first()); }
constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
// for rvc
int compressed_raw_encoding() const {
return raw_encoding() - compressed_register_base;
}
int compressed_encoding() const {
assert(is_compressed_valid(), "invalid compressed register");
return encoding() - compressed_register_base;
}
bool is_compressed_valid() const {
return raw_encoding() >= compressed_register_base &&
raw_encoding() <= compressed_register_top;
}
// derived registers, offsets, and addresses
inline Register successor() const;
VMReg as_VMReg() const;
const char* name() const;
};
inline friend constexpr Register as_Register(int encoding);
constexpr Register() : _encoding(-1) {} // noreg
int operator==(const Register r) const { return _encoding == r._encoding; }
int operator!=(const Register r) const { return _encoding != r._encoding; }
constexpr const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; }
};
extern Register::RegisterImpl all_RegisterImpls[Register::number_of_registers + 1] INTERNAL_VISIBILITY;
inline constexpr const Register::RegisterImpl* Register::RegisterImpl::first() {
return all_RegisterImpls + 1;
}
constexpr Register noreg = Register();
inline constexpr Register as_Register(int encoding) {
if (0 <= encoding && encoding < Register::number_of_registers) {
return Register(encoding);
}
return noreg;
}
inline Register Register::RegisterImpl::successor() const {
assert(is_valid(), "sanity");
return as_Register(encoding() + 1);
}
// The integer registers of RISCV architecture
constexpr Register x0 = as_Register( 0);
constexpr Register x1 = as_Register( 1);
constexpr Register x2 = as_Register( 2);
constexpr Register x3 = as_Register( 3);
constexpr Register x4 = as_Register( 4);
constexpr Register x5 = as_Register( 5);
constexpr Register x6 = as_Register( 6);
constexpr Register x7 = as_Register( 7);
constexpr Register x8 = as_Register( 8);
constexpr Register x9 = as_Register( 9);
constexpr Register x10 = as_Register(10);
constexpr Register x11 = as_Register(11);
constexpr Register x12 = as_Register(12);
constexpr Register x13 = as_Register(13);
constexpr Register x14 = as_Register(14);
constexpr Register x15 = as_Register(15);
constexpr Register x16 = as_Register(16);
constexpr Register x17 = as_Register(17);
constexpr Register x18 = as_Register(18);
constexpr Register x19 = as_Register(19);
constexpr Register x20 = as_Register(20);
constexpr Register x21 = as_Register(21);
constexpr Register x22 = as_Register(22);
constexpr Register x23 = as_Register(23);
constexpr Register x24 = as_Register(24);
constexpr Register x25 = as_Register(25);
constexpr Register x26 = as_Register(26);
constexpr Register x27 = as_Register(27);
constexpr Register x28 = as_Register(28);
constexpr Register x29 = as_Register(29);
constexpr Register x30 = as_Register(30);
constexpr Register x31 = as_Register(31);
// The implementation of floating point registers for the architecture
class FloatRegister {
private:
int _encoding;
constexpr explicit FloatRegister(int encoding) : _encoding(encoding) {}
public:
inline friend constexpr FloatRegister as_FloatRegister(int encoding);
enum {
number_of_registers = 32,
max_slots_per_register = 2,
// float registers in the range of [f8~f15] correspond to RVC. Please see Table 16.2 in spec.
compressed_register_base = 8,
compressed_register_top = 15,
};
class FloatRegisterImpl: public AbstractRegisterImpl {
friend class FloatRegister;
static constexpr const FloatRegisterImpl* first();
public:
// accessors
constexpr int raw_encoding() const { return checked_cast<int>(this - first()); }
constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
// for rvc
int compressed_raw_encoding() const {
return raw_encoding() - compressed_register_base;
}
int compressed_encoding() const {
assert(is_compressed_valid(), "invalid compressed register");
return encoding() - compressed_register_base;
}
bool is_compressed_valid() const {
return raw_encoding() >= compressed_register_base &&
raw_encoding() <= compressed_register_top;
}
// derived registers, offsets, and addresses
inline FloatRegister successor() const;
VMReg as_VMReg() const;
const char* name() const;
};
constexpr FloatRegister() : _encoding(-1) {} // fnoreg
int operator==(const FloatRegister r) const { return _encoding == r._encoding; }
int operator!=(const FloatRegister r) const { return _encoding != r._encoding; }
constexpr const FloatRegisterImpl* operator->() const { return FloatRegisterImpl::first() + _encoding; }
};
extern FloatRegister::FloatRegisterImpl all_FloatRegisterImpls[FloatRegister::number_of_registers + 1] INTERNAL_VISIBILITY;
inline constexpr const FloatRegister::FloatRegisterImpl* FloatRegister::FloatRegisterImpl::first() {
return all_FloatRegisterImpls + 1;
}
constexpr FloatRegister fnoreg = FloatRegister();
inline constexpr FloatRegister as_FloatRegister(int encoding) {
if (0 <= encoding && encoding < FloatRegister::number_of_registers) {
return FloatRegister(encoding);
}
return fnoreg;
}
inline FloatRegister FloatRegister::FloatRegisterImpl::successor() const {
assert(is_valid(), "sanity");
return as_FloatRegister(encoding() + 1);
}
// The float registers of the RISCV architecture
constexpr FloatRegister f0 = as_FloatRegister( 0);
constexpr FloatRegister f1 = as_FloatRegister( 1);
constexpr FloatRegister f2 = as_FloatRegister( 2);
constexpr FloatRegister f3 = as_FloatRegister( 3);
constexpr FloatRegister f4 = as_FloatRegister( 4);
constexpr FloatRegister f5 = as_FloatRegister( 5);
constexpr FloatRegister f6 = as_FloatRegister( 6);
constexpr FloatRegister f7 = as_FloatRegister( 7);
constexpr FloatRegister f8 = as_FloatRegister( 8);
constexpr FloatRegister f9 = as_FloatRegister( 9);
constexpr FloatRegister f10 = as_FloatRegister(10);
constexpr FloatRegister f11 = as_FloatRegister(11);
constexpr FloatRegister f12 = as_FloatRegister(12);
constexpr FloatRegister f13 = as_FloatRegister(13);
constexpr FloatRegister f14 = as_FloatRegister(14);
constexpr FloatRegister f15 = as_FloatRegister(15);
constexpr FloatRegister f16 = as_FloatRegister(16);
constexpr FloatRegister f17 = as_FloatRegister(17);
constexpr FloatRegister f18 = as_FloatRegister(18);
constexpr FloatRegister f19 = as_FloatRegister(19);
constexpr FloatRegister f20 = as_FloatRegister(20);
constexpr FloatRegister f21 = as_FloatRegister(21);
constexpr FloatRegister f22 = as_FloatRegister(22);
constexpr FloatRegister f23 = as_FloatRegister(23);
constexpr FloatRegister f24 = as_FloatRegister(24);
constexpr FloatRegister f25 = as_FloatRegister(25);
constexpr FloatRegister f26 = as_FloatRegister(26);
constexpr FloatRegister f27 = as_FloatRegister(27);
constexpr FloatRegister f28 = as_FloatRegister(28);
constexpr FloatRegister f29 = as_FloatRegister(29);
constexpr FloatRegister f30 = as_FloatRegister(30);
constexpr FloatRegister f31 = as_FloatRegister(31);
// The implementation of vector registers for RVV
class VectorRegister {
int _encoding;
constexpr explicit VectorRegister(int encoding) : _encoding(encoding) {}
public:
inline friend constexpr VectorRegister as_VectorRegister(int encoding);
enum {
number_of_registers = 32,
max_slots_per_register = 4
};
class VectorRegisterImpl: public AbstractRegisterImpl {
friend class VectorRegister;
static constexpr const VectorRegisterImpl* first();
public:
// accessors
constexpr int raw_encoding() const { return checked_cast<int>(this - first()); }
constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; }
// derived registers, offsets, and addresses
inline VectorRegister successor() const;
VMReg as_VMReg() const;
const char* name() const;
};
constexpr VectorRegister() : _encoding(-1) {} // vnoreg
int operator==(const VectorRegister r) const { return _encoding == r._encoding; }
int operator!=(const VectorRegister r) const { return _encoding != r._encoding; }
constexpr const VectorRegisterImpl* operator->() const { return VectorRegisterImpl::first() + _encoding; }
};
extern VectorRegister::VectorRegisterImpl all_VectorRegisterImpls[VectorRegister::number_of_registers + 1] INTERNAL_VISIBILITY;
inline constexpr const VectorRegister::VectorRegisterImpl* VectorRegister::VectorRegisterImpl::first() {
return all_VectorRegisterImpls + 1;
}
constexpr VectorRegister vnoreg = VectorRegister();
inline constexpr VectorRegister as_VectorRegister(int encoding) {
if (0 <= encoding && encoding < VectorRegister::number_of_registers) {
return VectorRegister(encoding);
}
return vnoreg;
}
inline VectorRegister VectorRegister::VectorRegisterImpl::successor() const {
assert(is_valid(), "sanity");
return as_VectorRegister(encoding() + 1);
}
// The vector registers of RVV
constexpr VectorRegister v0 = as_VectorRegister( 0);
constexpr VectorRegister v1 = as_VectorRegister( 1);
constexpr VectorRegister v2 = as_VectorRegister( 2);
constexpr VectorRegister v3 = as_VectorRegister( 3);
constexpr VectorRegister v4 = as_VectorRegister( 4);
constexpr VectorRegister v5 = as_VectorRegister( 5);
constexpr VectorRegister v6 = as_VectorRegister( 6);
constexpr VectorRegister v7 = as_VectorRegister( 7);
constexpr VectorRegister v8 = as_VectorRegister( 8);
constexpr VectorRegister v9 = as_VectorRegister( 9);
constexpr VectorRegister v10 = as_VectorRegister(10);
constexpr VectorRegister v11 = as_VectorRegister(11);
constexpr VectorRegister v12 = as_VectorRegister(12);
constexpr VectorRegister v13 = as_VectorRegister(13);
constexpr VectorRegister v14 = as_VectorRegister(14);
constexpr VectorRegister v15 = as_VectorRegister(15);
constexpr VectorRegister v16 = as_VectorRegister(16);
constexpr VectorRegister v17 = as_VectorRegister(17);
constexpr VectorRegister v18 = as_VectorRegister(18);
constexpr VectorRegister v19 = as_VectorRegister(19);
constexpr VectorRegister v20 = as_VectorRegister(20);
constexpr VectorRegister v21 = as_VectorRegister(21);
constexpr VectorRegister v22 = as_VectorRegister(22);
constexpr VectorRegister v23 = as_VectorRegister(23);
constexpr VectorRegister v24 = as_VectorRegister(24);
constexpr VectorRegister v25 = as_VectorRegister(25);
constexpr VectorRegister v26 = as_VectorRegister(26);
constexpr VectorRegister v27 = as_VectorRegister(27);
constexpr VectorRegister v28 = as_VectorRegister(28);
constexpr VectorRegister v29 = as_VectorRegister(29);
constexpr VectorRegister v30 = as_VectorRegister(30);
constexpr VectorRegister v31 = as_VectorRegister(31);
// Need to know the total number of registers of all sorts for SharedInfo.
// Define a class that exports it.
class ConcreteRegisterImpl : public AbstractRegisterImpl {
public:
enum {
max_gpr = Register::number_of_registers * Register::max_slots_per_register,
max_fpr = max_gpr + FloatRegister::number_of_registers * FloatRegister::max_slots_per_register,
max_vpr = max_fpr + VectorRegister::number_of_registers * VectorRegister::max_slots_per_register,
// A big enough number for C2: all the registers plus flags
// This number must be large enough to cover REG_COUNT (defined by c2) registers.
// There is no requirement that any ordering here matches any ordering c2 gives
// it's optoregs.
number_of_registers = max_vpr // gpr/fpr/vpr
};
};
typedef AbstractRegSet<Register> RegSet;
typedef AbstractRegSet<FloatRegister> FloatRegSet;
typedef AbstractRegSet<VectorRegister> VectorRegSet;
template <>
inline Register AbstractRegSet<Register>::first() {
uint32_t first = _bitset & -_bitset;
return first ? as_Register(exact_log2(first)) : noreg;
}
template <>
inline FloatRegister AbstractRegSet<FloatRegister>::first() {
uint32_t first = _bitset & -_bitset;
return first ? as_FloatRegister(exact_log2(first)) : fnoreg;
}
template<>
inline VectorRegister AbstractRegSet<VectorRegister>::first() {
uint32_t first = _bitset & -_bitset;
return first ? as_VectorRegister(exact_log2(first)) : vnoreg;
}
#endif // CPU_RISCV_REGISTER_RISCV_HPP