Create a super rough prototype of B3
[WebKit-https.git] / Source / JavaScriptCore / jit / Reg.h
1 /*
2  * Copyright (C) 2014 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 Reg_h
27 #define Reg_h
28
29 #if ENABLE(JIT)
30
31 #include "MacroAssembler.h"
32
33 namespace JSC {
34
35 // Reg is a polymorphic register class. It can refer to either integer or float registers.
36 // Here are some use cases:
37 //
38 // GPRReg gpr;
39 // Reg reg = gpr;
40 // reg.isSet() == true
41 // reg.isGPR() == true
42 // reg.isFPR() == false
43 //
44 // for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
45 //     if (reg.isGPR()) {
46 //     } else /* reg.isFPR() */ {
47 //     }
48 // }
49 //
50 // The above loop could have also used !!reg or reg.isSet() as a condition.
51
52 class Reg {
53 public:
54     Reg()
55         : m_index(invalid())
56     {
57     }
58
59     Reg(WTF::HashTableDeletedValueType)
60         : m_index(deleted())
61     {
62     }
63     
64     Reg(MacroAssembler::RegisterID reg)
65         : m_index(MacroAssembler::registerIndex(reg))
66     {
67     }
68     
69     Reg(MacroAssembler::FPRegisterID reg)
70         : m_index(MacroAssembler::registerIndex(reg))
71     {
72     }
73     
74     static Reg fromIndex(unsigned index)
75     {
76         Reg result;
77         result.m_index = index;
78         return result;
79     }
80     
81     static Reg first()
82     {
83         Reg result;
84         result.m_index = 0;
85         return result;
86     }
87     
88     static Reg last()
89     {
90         Reg result;
91         result.m_index = MacroAssembler::numberOfRegisters() + MacroAssembler::numberOfFPRegisters() - 1;
92         return result;
93     }
94     
95     Reg next() const
96     {
97         ASSERT(!!*this);
98         if (*this == last())
99             return Reg();
100         Reg result;
101         result.m_index = m_index + 1;
102         return result;
103     }
104     
105     unsigned index() const { return m_index; }
106     
107     bool isSet() const { return m_index != invalid(); }
108     explicit operator bool() const { return isSet(); }
109
110     bool isHashTableDeletedValue() const { return m_index == deleted(); }
111     
112     bool isGPR() const
113     {
114         return m_index < MacroAssembler::numberOfRegisters();
115     }
116     
117     bool isFPR() const
118     {
119         return (m_index - MacroAssembler::numberOfRegisters()) < MacroAssembler::numberOfFPRegisters();
120     }
121     
122     MacroAssembler::RegisterID gpr() const
123     {
124         ASSERT(isGPR());
125         return static_cast<MacroAssembler::RegisterID>(MacroAssembler::firstRegister() + m_index);
126     }
127     
128     MacroAssembler::FPRegisterID fpr() const
129     {
130         ASSERT(isFPR());
131         return static_cast<MacroAssembler::FPRegisterID>(
132             MacroAssembler::firstFPRegister() + (m_index - MacroAssembler::numberOfRegisters()));
133     }
134     
135     bool operator==(const Reg& other) const
136     {
137         return m_index == other.m_index;
138     }
139     
140     bool operator!=(const Reg& other) const
141     {
142         return m_index != other.m_index;
143     }
144     
145     bool operator<(const Reg& other) const
146     {
147         return m_index < other.m_index;
148     }
149     
150     bool operator>(const Reg& other) const
151     {
152         return m_index > other.m_index;
153     }
154     
155     bool operator<=(const Reg& other) const
156     {
157         return m_index <= other.m_index;
158     }
159     
160     bool operator>=(const Reg& other) const
161     {
162         return m_index >= other.m_index;
163     }
164     
165     unsigned hash() const
166     {
167         return m_index;
168     }
169     
170     void dump(PrintStream&) const;
171
172     class AllRegsIterable {
173     public:
174
175         class iterator {
176         public:
177             iterator() { }
178
179             explicit iterator(Reg reg)
180                 : m_regIndex(reg.index())
181             {
182             }
183
184             Reg operator*() const { return Reg::fromIndex(m_regIndex); }
185
186             iterator& operator++()
187             {
188                 m_regIndex = Reg::fromIndex(m_regIndex).next().index();
189                 return *this;
190             }
191
192             bool operator==(const iterator& other) const
193             {
194                 return m_regIndex == other.m_regIndex;
195             }
196
197             bool operator!=(const iterator& other) const
198             {
199                 return !(*this == other);
200             }
201
202         private:
203             unsigned m_regIndex;
204         };
205
206         iterator begin() const { return iterator(Reg::first()); }
207         iterator end() const { return iterator(Reg()); }
208     };
209
210     static AllRegsIterable all() { return AllRegsIterable(); }
211
212 private:
213     static uint8_t invalid() { return 0xff; }
214
215     static uint8_t deleted() { return 0xfe; }
216     
217     uint8_t m_index;
218 };
219
220 struct RegHash {
221     static unsigned hash(const Reg& key) { return key.hash(); }
222     static bool equal(const Reg& a, const Reg& b) { return a == b; }
223     static const bool safeToCompareToEmptyOrDeleted = true;
224 };
225
226 } // namespace JSC
227
228 namespace WTF {
229
230 template<typename T> struct DefaultHash;
231 template<> struct DefaultHash<JSC::Reg> {
232     typedef JSC::RegHash Hash;
233 };
234
235 template<typename T> struct HashTraits;
236 template<> struct HashTraits<JSC::Reg> : SimpleClassHashTraits<JSC::Reg> {
237     static const bool emptyValueIsZero = false;
238  };
239
240 } // namespace WTF
241
242 #endif // ENABLE(JIT)
243
244 #endif // Reg_h
245