blob: f406995b8ac0e8a0315d3d7d49bae04869d22c99 [file] [edit]
/*
* Copyright (c) 2000, 2024, 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 SHARE_ASM_REGISTER_HPP
#define SHARE_ASM_REGISTER_HPP
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/population_count.hpp"
// Use AbstractRegister as shortcut
class AbstractRegisterImpl;
typedef AbstractRegisterImpl* AbstractRegister;
// The super class for platform specific registers. Instead of using value objects,
// registers are implemented as pointers. Subclassing is used so all registers can
// use the debugging support below. No virtual functions are used for efficiency.
// They are canonicalized; i.e., registers are equal if their pointers are equal,
// and vice versa. A concrete implementation may just map the register onto 'this'.
class AbstractRegisterImpl {
protected:
int value() const { return (int)(intx)this; }
};
// Macros to help define all kinds of registers
#ifndef USE_POINTERS_TO_REGISTER_IMPL_ARRAY
#define AS_REGISTER(type,name) ((type)name##_##type##EnumValue)
#define CONSTANT_REGISTER_DECLARATION(type, name, value) \
const type name = ((type)value); \
enum { name##_##type##EnumValue = (value) }
#else // USE_POINTERS_TO_REGISTER_IMPL_ARRAY
#define REGISTER_IMPL_DECLARATION(type, impl_type, reg_count) \
inline constexpr type as_ ## type(int encoding) { \
return impl_type::first() + encoding; \
} \
extern impl_type all_ ## type ## s[reg_count + 1] INTERNAL_VISIBILITY; \
inline constexpr type impl_type::first() { return all_ ## type ## s + 1; }
#define REGISTER_IMPL_DEFINITION(type, impl_type, reg_count) \
impl_type all_ ## type ## s[reg_count + 1];
#define CONSTANT_REGISTER_DECLARATION(type, name, value) \
constexpr type name = as_ ## type(value);
#endif // USE_POINTERS_TO_REGISTER_IMPL_ARRAY
#define REGISTER_DECLARATION(type, name, value) \
const type name = ((type)value)
// For definitions of RegisterImpl* instances. To be redefined in an
// OS-specific way.
#ifdef __GNUC__
#define INTERNAL_VISIBILITY __attribute__ ((visibility ("internal")))
#else
#define INTERNAL_VISIBILITY
#endif
template <class RegImpl> class RegSetIterator;
template <class RegImpl> class ReverseRegSetIterator;
// A set of registers
template <class RegImpl>
class AbstractRegSet {
#ifndef ARM
STATIC_ASSERT(RegImpl::number_of_registers <= 64);
#endif
uint64_t _bitset;
constexpr AbstractRegSet(uint64_t bitset) : _bitset(bitset) { }
static constexpr int max_size() {
return (int)(sizeof(_bitset) * BitsPerByte);
}
public:
constexpr AbstractRegSet() : _bitset(0) { }
constexpr AbstractRegSet(RegImpl r1)
: _bitset(r1->is_valid() ? size_t(1) << r1->encoding() : 0) {
}
constexpr AbstractRegSet operator+(const AbstractRegSet aSet) const {
AbstractRegSet result(_bitset | aSet._bitset);
return result;
}
constexpr AbstractRegSet operator-(const AbstractRegSet aSet) const {
AbstractRegSet result(_bitset & ~aSet._bitset);
return result;
}
constexpr AbstractRegSet &operator+=(const AbstractRegSet aSet) {
*this = *this + aSet;
return *this;
}
constexpr AbstractRegSet &operator-=(const AbstractRegSet aSet) {
*this = *this - aSet;
return *this;
}
constexpr static AbstractRegSet of(RegImpl r1) {
return AbstractRegSet(r1);
}
constexpr static AbstractRegSet of(RegImpl r1, RegImpl r2) {
return of(r1) + r2;
}
constexpr static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3) {
return of(r1, r2) + r3;
}
constexpr static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3, RegImpl r4) {
return of(r1, r2, r3) + r4;
}
constexpr static AbstractRegSet range(RegImpl start, RegImpl end) {
int start_enc = start->encoding();
int end_enc = end->encoding();
assert(start_enc <= end_enc, "must be");
size_t bits = ~(size_t)0;
bits <<= start_enc;
bits <<= max_size() - 1 - end_enc;
bits >>= max_size() - 1 - end_enc;
return AbstractRegSet(bits);
}
constexpr bool contains(RegImpl reg) {
return (AbstractRegSet(reg).bits() & bits()) != 0;
}
constexpr uint size() const { return population_count(_bitset); }
constexpr uint64_t bits() const { return _bitset; }
private:
RegImpl first();
RegImpl last();
public:
friend class RegSetIterator<RegImpl>;
friend class ReverseRegSetIterator<RegImpl>;
RegSetIterator<RegImpl> begin();
ReverseRegSetIterator<RegImpl> rbegin();
};
template <class RegImpl>
class RegSetIterator {
AbstractRegSet<RegImpl> _regs;
public:
RegSetIterator(AbstractRegSet<RegImpl> x): _regs(x) {}
RegSetIterator(const RegSetIterator& mit) : _regs(mit._regs) {}
RegSetIterator& operator++() {
RegImpl r = _regs.first();
if (r->is_valid())
_regs -= r;
return *this;
}
RegSetIterator operator++(int) {
RegSetIterator r = *this;
++(*this);
return r;
}
RegSetIterator<RegImpl>& operator=(const RegSetIterator<RegImpl>& mit) {
_regs= mit._regs;
return *this;
}
bool operator==(const RegSetIterator& rhs) const {
return _regs.bits() == rhs._regs.bits();
}
bool operator!=(const RegSetIterator& rhs) const {
return ! (rhs == *this);
}
RegImpl operator*() {
return _regs.first();
}
AbstractRegSet<RegImpl> remaining() const {
return _regs;
}
};
template <class RegImpl>
inline RegSetIterator<RegImpl> AbstractRegSet<RegImpl>::begin() {
return RegSetIterator<RegImpl>(*this);
}
template <class RegImpl>
class ReverseRegSetIterator {
AbstractRegSet<RegImpl> _regs;
public:
ReverseRegSetIterator(AbstractRegSet<RegImpl> x): _regs(x) {}
ReverseRegSetIterator(const ReverseRegSetIterator& mit) : _regs(mit._regs) {}
ReverseRegSetIterator& operator++() {
RegImpl r = _regs.last();
if (r->is_valid())
_regs -= r;
return *this;
}
bool operator==(const ReverseRegSetIterator& rhs) const {
return _regs.bits() == rhs._regs.bits();
}
bool operator!=(const ReverseRegSetIterator& rhs) const {
return ! (rhs == *this);
}
RegImpl operator*() {
return _regs.last();
}
};
template <class RegImpl>
inline ReverseRegSetIterator<RegImpl> AbstractRegSet<RegImpl>::rbegin() {
return ReverseRegSetIterator<RegImpl>(*this);
}
#include CPU_HEADER(register)
// Debugging and assertion support
template<typename R>
constexpr bool different_registers(AbstractRegSet<R> allocated_regs, R first_register) {
return !allocated_regs.contains(first_register);
}
template<typename R, typename... Rx>
constexpr bool different_registers(AbstractRegSet<R> allocated_regs, R first_register, Rx... more_registers) {
if (allocated_regs.contains(first_register)) {
return false;
}
return different_registers(allocated_regs + first_register, more_registers...);
}
template<typename R, typename... Rx>
inline constexpr bool different_registers(R first_register, Rx... more_registers) {
return different_registers(AbstractRegSet<R>(first_register), more_registers...);
}
template<typename R, typename... Rx>
inline void assert_different_registers_impl(const char* file, int line, R first_register, Rx... more_registers) {
#ifdef ASSERT
if (!different_registers(first_register, more_registers...)) {
const R regs[] = { first_register, more_registers... };
// Find a duplicate entry.
for (size_t i = 0; i < ARRAY_SIZE(regs) - 1; ++i) {
for (size_t j = i + 1; j < ARRAY_SIZE(regs); ++j) {
if (regs[i]->is_valid()) {
assert_with_file_and_line(regs[i] != regs[j], file, line, "regs[%zu] and regs[%zu] are both: %s",
i, j, regs[i]->name());
}
}
}
}
#endif
}
#define assert_different_registers(...) assert_different_registers_impl(__FILE__, __LINE__, __VA_ARGS__)
#endif // SHARE_ASM_REGISTER_HPP