1/*
2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#if ENABLE(ASSEMBLER)
29
30#include "FPRInfo.h"
31#include "GPRInfo.h"
32
33namespace JSC {
34
35class RegisterSet;
36
37class TempRegisterSet {
38public:
39 TempRegisterSet()
40 {
41 clearAll();
42 }
43
44 TempRegisterSet(const RegisterSet&);
45
46 void set(GPRReg reg)
47 {
48 setBit(GPRInfo::toIndex(reg));
49 }
50
51 void set(JSValueRegs regs)
52 {
53 if (regs.tagGPR() != InvalidGPRReg)
54 set(regs.tagGPR());
55 set(regs.payloadGPR());
56 }
57
58 void setGPRByIndex(unsigned index)
59 {
60 ASSERT(index < GPRInfo::numberOfRegisters);
61 setBit(index);
62 }
63
64 void clear(GPRReg reg)
65 {
66 clearBit(GPRInfo::toIndex(reg));
67 }
68
69 bool get(GPRReg reg) const
70 {
71 return getBit(GPRInfo::toIndex(reg));
72 }
73
74 bool getGPRByIndex(unsigned index) const
75 {
76 ASSERT(index < GPRInfo::numberOfRegisters);
77 return getBit(index);
78 }
79
80 // Return the index'th free GPR.
81 GPRReg getFreeGPR(unsigned index = 0) const
82 {
83 for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
84 if (!getGPRByIndex(i) && !index--)
85 return GPRInfo::toRegister(i);
86 }
87 return InvalidGPRReg;
88 }
89
90 void set(FPRReg reg)
91 {
92 setBit(GPRInfo::numberOfRegisters + FPRInfo::toIndex(reg));
93 }
94
95 void setFPRByIndex(unsigned index)
96 {
97 ASSERT(index < FPRInfo::numberOfRegisters);
98 setBit(GPRInfo::numberOfRegisters + index);
99 }
100
101 void clear(FPRReg reg)
102 {
103 clearBit(GPRInfo::numberOfRegisters + FPRInfo::toIndex(reg));
104 }
105
106 bool get(FPRReg reg) const
107 {
108 return getBit(GPRInfo::numberOfRegisters + FPRInfo::toIndex(reg));
109 }
110
111 bool getFPRByIndex(unsigned index) const
112 {
113 ASSERT(index < FPRInfo::numberOfRegisters);
114 return getBit(GPRInfo::numberOfRegisters + index);
115 }
116
117 // Return the index'th free FPR.
118 FPRReg getFreeFPR(unsigned index = 0) const
119 {
120 for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
121 if (!getFPRByIndex(i) && !index--)
122 return FPRInfo::toRegister(i);
123 }
124 return InvalidFPRReg;
125 }
126
127 template<typename BankInfo>
128 void setByIndex(unsigned index)
129 {
130 set(BankInfo::toRegister(index));
131 }
132
133 template<typename BankInfo>
134 bool getByIndex(unsigned index)
135 {
136 return get(BankInfo::toRegister(index));
137 }
138
139 unsigned numberOfSetGPRs() const
140 {
141 unsigned result = 0;
142 for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
143 if (!getBit(i))
144 continue;
145 result++;
146 }
147 return result;
148 }
149
150 unsigned numberOfSetFPRs() const
151 {
152 unsigned result = 0;
153 for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
154 if (!getBit(GPRInfo::numberOfRegisters + i))
155 continue;
156 result++;
157 }
158 return result;
159 }
160
161 unsigned numberOfSetRegisters() const
162 {
163 unsigned result = 0;
164 for (unsigned i = totalNumberOfRegisters; i--;) {
165 if (!getBit(i))
166 continue;
167 result++;
168 }
169 return result;
170 }
171
172private:
173 void clearAll()
174 {
175 for (unsigned i = numberOfBytesInTempRegisterSet; i--;)
176 m_set[i] = 0;
177 }
178
179 void setBit(unsigned i)
180 {
181 ASSERT(i < totalNumberOfRegisters);
182 m_set[i >> 3] |= (1 << (i & 7));
183 }
184
185 void clearBit(unsigned i)
186 {
187 ASSERT(i < totalNumberOfRegisters);
188 m_set[i >> 3] &= ~(1 << (i & 7));
189 }
190
191 bool getBit(unsigned i) const
192 {
193 ASSERT(i < totalNumberOfRegisters);
194 return !!(m_set[i >> 3] & (1 << (i & 7)));
195 }
196
197 static const unsigned totalNumberOfRegisters =
198 GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters;
199
200 static const unsigned numberOfBytesInTempRegisterSet =
201 (totalNumberOfRegisters + 7) >> 3;
202
203 uint8_t m_set[numberOfBytesInTempRegisterSet];
204};
205
206} // namespace JSC
207
208#else // ENABLE(ASSEMBLER) -> so if JIT is disabled
209
210namespace JSC {
211
212// Define TempRegisterSet to something, to make it easier to refer to this type in code that
213// make be compiled when the JIT is disabled.
214
215struct TempRegisterSet { };
216
217} // namespace JSC
218
219#endif // ENABLE(ASSEMBLER)
220