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#ifndef TempRegisterSet_h
27#define TempRegisterSet_h
28
29#if ENABLE(JIT)
30
31#include "FPRInfo.h"
32#include "GPRInfo.h"
33
34namespace JSC {
35
36class RegisterSet;
37
38class TempRegisterSet {
39public:
40    TempRegisterSet()
41    {
42        clearAll();
43    }
44
45    TempRegisterSet(const RegisterSet&);
46
47    void set(GPRReg reg)
48    {
49        setBit(GPRInfo::toIndex(reg));
50    }
51
52    void set(JSValueRegs regs)
53    {
54        if (regs.tagGPR() != InvalidGPRReg)
55            set(regs.tagGPR());
56        set(regs.payloadGPR());
57    }
58
59    void setGPRByIndex(unsigned index)
60    {
61        ASSERT(index < GPRInfo::numberOfRegisters);
62        setBit(index);
63    }
64
65    void clear(GPRReg reg)
66    {
67        clearBit(GPRInfo::toIndex(reg));
68    }
69
70    bool get(GPRReg reg) const
71    {
72        return getBit(GPRInfo::toIndex(reg));
73    }
74
75    bool getGPRByIndex(unsigned index) const
76    {
77        ASSERT(index < GPRInfo::numberOfRegisters);
78        return getBit(index);
79    }
80
81    // Return the index'th free GPR.
82    GPRReg getFreeGPR(unsigned index = 0) const
83    {
84        for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
85            if (!getGPRByIndex(i) && !index--)
86                return GPRInfo::toRegister(i);
87        }
88        return InvalidGPRReg;
89    }
90
91    void set(FPRReg reg)
92    {
93        setBit(GPRInfo::numberOfRegisters + FPRInfo::toIndex(reg));
94    }
95
96    void setFPRByIndex(unsigned index)
97    {
98        ASSERT(index < FPRInfo::numberOfRegisters);
99        setBit(GPRInfo::numberOfRegisters + index);
100    }
101
102    void clear(FPRReg reg)
103    {
104        clearBit(GPRInfo::numberOfRegisters + FPRInfo::toIndex(reg));
105    }
106
107    bool get(FPRReg reg) const
108    {
109        return getBit(GPRInfo::numberOfRegisters + FPRInfo::toIndex(reg));
110    }
111
112    bool getFPRByIndex(unsigned index) const
113    {
114        ASSERT(index < FPRInfo::numberOfRegisters);
115        return getBit(GPRInfo::numberOfRegisters + index);
116    }
117
118    template<typename BankInfo>
119    void setByIndex(unsigned index)
120    {
121        set(BankInfo::toRegister(index));
122    }
123
124    template<typename BankInfo>
125    bool getByIndex(unsigned index)
126    {
127        return get(BankInfo::toRegister(index));
128    }
129
130    unsigned numberOfSetGPRs() const
131    {
132        unsigned result = 0;
133        for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
134            if (!getBit(i))
135                continue;
136            result++;
137        }
138        return result;
139    }
140
141    unsigned numberOfSetFPRs() const
142    {
143        unsigned result = 0;
144        for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
145            if (!getBit(GPRInfo::numberOfRegisters + i))
146                continue;
147            result++;
148        }
149        return result;
150    }
151
152    unsigned numberOfSetRegisters() const
153    {
154        unsigned result = 0;
155        for (unsigned i = totalNumberOfRegisters; i--;) {
156            if (!getBit(i))
157                continue;
158            result++;
159        }
160        return result;
161    }
162
163private:
164    void clearAll()
165    {
166        for (unsigned i = numberOfBytesInTempRegisterSet; i--;)
167            m_set[i] = 0;
168    }
169
170    void setBit(unsigned i)
171    {
172        ASSERT(i < totalNumberOfRegisters);
173        m_set[i >> 3] |= (1 << (i & 7));
174    }
175
176    void clearBit(unsigned i)
177    {
178        ASSERT(i < totalNumberOfRegisters);
179        m_set[i >> 3] &= ~(1 << (i & 7));
180    }
181
182    bool getBit(unsigned i) const
183    {
184        ASSERT(i < totalNumberOfRegisters);
185        return !!(m_set[i >> 3] & (1 << (i & 7)));
186    }
187
188    static const unsigned totalNumberOfRegisters =
189        GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters;
190
191    static const unsigned numberOfBytesInTempRegisterSet =
192        (totalNumberOfRegisters + 7) >> 3;
193
194    uint8_t m_set[numberOfBytesInTempRegisterSet];
195};
196
197} // namespace JSC
198
199#else // ENABLE(JIT) -> so if JIT is disabled
200
201namespace JSC {
202
203// Define TempRegisterSet to something, to make it easier to refer to this type in code that
204// make be compiled when the JIT is disabled.
205
206struct TempRegisterSet { };
207
208} // namespace JSC
209
210#endif // ENABLE(JIT)
211
212#endif // TempRegisterSet_h
213
214