1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_REGISTER_CONFIGURATION_H_
6#define V8_REGISTER_CONFIGURATION_H_
7
8#include "src/base/macros.h"
9#include "src/globals.h"
10#include "src/machine-type.h"
11#include "src/reglist.h"
12#include "src/utils.h"
13
14namespace v8 {
15namespace internal {
16
17// An architecture independent representation of the sets of registers available
18// for instruction creation.
19class V8_EXPORT_PRIVATE RegisterConfiguration {
20 public:
21 enum AliasingKind {
22 // Registers alias a single register of every other size (e.g. Intel).
23 OVERLAP,
24 // Registers alias two registers of the next smaller size (e.g. ARM).
25 COMBINE
26 };
27
28 // Architecture independent maxes.
29 static constexpr int kMaxGeneralRegisters = 32;
30 static constexpr int kMaxFPRegisters = 32;
31 static constexpr int kMaxRegisters =
32 Max(kMaxFPRegisters, kMaxGeneralRegisters);
33
34 // Default RegisterConfigurations for the target architecture.
35 static const RegisterConfiguration* Default();
36
37 // Register configuration with reserved masking register.
38 static const RegisterConfiguration* Poisoning();
39
40 static const RegisterConfiguration* RestrictGeneralRegisters(
41 RegList registers);
42
43 RegisterConfiguration(int num_general_registers, int num_double_registers,
44 int num_allocatable_general_registers,
45 int num_allocatable_double_registers,
46 const int* allocatable_general_codes,
47 const int* allocatable_double_codes,
48 AliasingKind fp_aliasing_kind);
49
50 int num_general_registers() const { return num_general_registers_; }
51 int num_float_registers() const { return num_float_registers_; }
52 int num_double_registers() const { return num_double_registers_; }
53 int num_simd128_registers() const { return num_simd128_registers_; }
54 int num_allocatable_general_registers() const {
55 return num_allocatable_general_registers_;
56 }
57 int num_allocatable_float_registers() const {
58 return num_allocatable_float_registers_;
59 }
60 int num_allocatable_double_registers() const {
61 return num_allocatable_double_registers_;
62 }
63 int num_allocatable_simd128_registers() const {
64 return num_allocatable_simd128_registers_;
65 }
66 AliasingKind fp_aliasing_kind() const { return fp_aliasing_kind_; }
67 int32_t allocatable_general_codes_mask() const {
68 return allocatable_general_codes_mask_;
69 }
70 int32_t allocatable_double_codes_mask() const {
71 return allocatable_double_codes_mask_;
72 }
73 int32_t allocatable_float_codes_mask() const {
74 return allocatable_float_codes_mask_;
75 }
76 int GetAllocatableGeneralCode(int index) const {
77 DCHECK(index >= 0 && index < num_allocatable_general_registers());
78 return allocatable_general_codes_[index];
79 }
80 bool IsAllocatableGeneralCode(int index) const {
81 return ((1 << index) & allocatable_general_codes_mask_) != 0;
82 }
83 int GetAllocatableFloatCode(int index) const {
84 DCHECK(index >= 0 && index < num_allocatable_float_registers());
85 return allocatable_float_codes_[index];
86 }
87 bool IsAllocatableFloatCode(int index) const {
88 return ((1 << index) & allocatable_float_codes_mask_) != 0;
89 }
90 int GetAllocatableDoubleCode(int index) const {
91 DCHECK(index >= 0 && index < num_allocatable_double_registers());
92 return allocatable_double_codes_[index];
93 }
94 bool IsAllocatableDoubleCode(int index) const {
95 return ((1 << index) & allocatable_double_codes_mask_) != 0;
96 }
97 int GetAllocatableSimd128Code(int index) const {
98 DCHECK(index >= 0 && index < num_allocatable_simd128_registers());
99 return allocatable_simd128_codes_[index];
100 }
101 bool IsAllocatableSimd128Code(int index) const {
102 return ((1 << index) & allocatable_simd128_codes_mask_) != 0;
103 }
104
105 const int* allocatable_general_codes() const {
106 return allocatable_general_codes_;
107 }
108 const int* allocatable_float_codes() const {
109 return allocatable_float_codes_;
110 }
111 const int* allocatable_double_codes() const {
112 return allocatable_double_codes_;
113 }
114 const int* allocatable_simd128_codes() const {
115 return allocatable_simd128_codes_;
116 }
117
118 // Aliasing calculations for floating point registers, when fp_aliasing_kind()
119 // is COMBINE. Currently only implemented for kFloat32, kFloat64, or kSimd128
120 // reps. Returns the number of aliases, and if > 0, alias_base_index is set to
121 // the index of the first alias.
122 int GetAliases(MachineRepresentation rep, int index,
123 MachineRepresentation other_rep, int* alias_base_index) const;
124 // Returns a value indicating whether two registers alias each other, when
125 // fp_aliasing_kind() is COMBINE. Currently implemented for kFloat32,
126 // kFloat64, or kSimd128 reps.
127 bool AreAliases(MachineRepresentation rep, int index,
128 MachineRepresentation other_rep, int other_index) const;
129
130 virtual ~RegisterConfiguration() = default;
131
132 private:
133 const int num_general_registers_;
134 int num_float_registers_;
135 const int num_double_registers_;
136 int num_simd128_registers_;
137 int num_allocatable_general_registers_;
138 int num_allocatable_float_registers_;
139 int num_allocatable_double_registers_;
140 int num_allocatable_simd128_registers_;
141 int32_t allocatable_general_codes_mask_;
142 int32_t allocatable_float_codes_mask_;
143 int32_t allocatable_double_codes_mask_;
144 int32_t allocatable_simd128_codes_mask_;
145 const int* allocatable_general_codes_;
146 int allocatable_float_codes_[kMaxFPRegisters];
147 const int* allocatable_double_codes_;
148 int allocatable_simd128_codes_[kMaxFPRegisters];
149 AliasingKind fp_aliasing_kind_;
150};
151
152} // namespace internal
153} // namespace v8
154
155#endif // V8_REGISTER_CONFIGURATION_H_
156