|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef jit_mips_Architecture_mips_h |
|
8 #define jit_mips_Architecture_mips_h |
|
9 |
|
10 #include <limits.h> |
|
11 #include <stdint.h> |
|
12 |
|
13 #include "js/Utility.h" |
|
14 |
|
15 // gcc appears to use _mips_hard_float to denote |
|
16 // that the target is a hard-float target. |
|
17 #ifdef _mips_hard_float |
|
18 #define JS_CODEGEN_MIPS_HARDFP |
|
19 #endif |
|
20 namespace js { |
|
21 namespace jit { |
|
22 |
|
23 // Shadow stack space is not required on MIPS. |
|
24 static const uint32_t ShadowStackSpace = 0; |
|
25 |
|
26 // These offsets are specific to nunboxing, and capture offsets into the |
|
27 // components of a js::Value. |
|
28 // Size of MIPS32 general purpose registers is 32 bits. |
|
29 static const int32_t NUNBOX32_TYPE_OFFSET = 4; |
|
30 static const int32_t NUNBOX32_PAYLOAD_OFFSET = 0; |
|
31 |
|
32 // Size of each bailout table entry. |
|
33 // For MIPS this is 2 instructions relative call. |
|
34 static const uint32_t BAILOUT_TABLE_ENTRY_SIZE = 2 * sizeof(void *); |
|
35 |
|
36 class Registers |
|
37 { |
|
38 public: |
|
39 enum RegisterID { |
|
40 r0 = 0, |
|
41 r1, |
|
42 r2, |
|
43 r3, |
|
44 r4, |
|
45 r5, |
|
46 r6, |
|
47 r7, |
|
48 r8, |
|
49 r9, |
|
50 r10, |
|
51 r11, |
|
52 r12, |
|
53 r13, |
|
54 r14, |
|
55 r15, |
|
56 r16, |
|
57 r17, |
|
58 r18, |
|
59 r19, |
|
60 r20, |
|
61 r21, |
|
62 r22, |
|
63 r23, |
|
64 r24, |
|
65 r25, |
|
66 r26, |
|
67 r27, |
|
68 r28, |
|
69 r29, |
|
70 r30, |
|
71 r31, |
|
72 zero = r0, |
|
73 at = r1, |
|
74 v0 = r2, |
|
75 v1 = r3, |
|
76 a0 = r4, |
|
77 a1 = r5, |
|
78 a2 = r6, |
|
79 a3 = r7, |
|
80 t0 = r8, |
|
81 t1 = r9, |
|
82 t2 = r10, |
|
83 t3 = r11, |
|
84 t4 = r12, |
|
85 t5 = r13, |
|
86 t6 = r14, |
|
87 t7 = r15, |
|
88 s0 = r16, |
|
89 s1 = r17, |
|
90 s2 = r18, |
|
91 s3 = r19, |
|
92 s4 = r20, |
|
93 s5 = r21, |
|
94 s6 = r22, |
|
95 s7 = r23, |
|
96 t8 = r24, |
|
97 t9 = r25, |
|
98 k0 = r26, |
|
99 k1 = r27, |
|
100 gp = r28, |
|
101 sp = r29, |
|
102 fp = r30, |
|
103 ra = r31, |
|
104 invalid_reg |
|
105 }; |
|
106 typedef RegisterID Code; |
|
107 |
|
108 static const char *GetName(Code code) { |
|
109 static const char * const Names[] = { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", |
|
110 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", |
|
111 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
|
112 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"}; |
|
113 return Names[code]; |
|
114 } |
|
115 static const char *GetName(uint32_t i) { |
|
116 JS_ASSERT(i < Total); |
|
117 return GetName(Code(i)); |
|
118 } |
|
119 |
|
120 static Code FromName(const char *name); |
|
121 |
|
122 static const Code StackPointer = sp; |
|
123 static const Code Invalid = invalid_reg; |
|
124 |
|
125 static const uint32_t Total = 32; |
|
126 static const uint32_t Allocatable = 14; |
|
127 |
|
128 static const uint32_t AllMask = 0xffffffff; |
|
129 static const uint32_t ArgRegMask = (1 << a0) | (1 << a1) | (1 << a2) | (1 << a3); |
|
130 |
|
131 static const uint32_t VolatileMask = |
|
132 (1 << Registers::v0) | |
|
133 (1 << Registers::v1) | |
|
134 (1 << Registers::a0) | |
|
135 (1 << Registers::a1) | |
|
136 (1 << Registers::a2) | |
|
137 (1 << Registers::a3) | |
|
138 (1 << Registers::t0) | |
|
139 (1 << Registers::t1) | |
|
140 (1 << Registers::t2) | |
|
141 (1 << Registers::t3) | |
|
142 (1 << Registers::t4) | |
|
143 (1 << Registers::t5) | |
|
144 (1 << Registers::t6) | |
|
145 (1 << Registers::t7); |
|
146 |
|
147 static const uint32_t NonVolatileMask = |
|
148 (1 << Registers::s0) | |
|
149 (1 << Registers::s1) | |
|
150 (1 << Registers::s2) | |
|
151 (1 << Registers::s3) | |
|
152 (1 << Registers::s4) | |
|
153 (1 << Registers::s5) | |
|
154 (1 << Registers::s6) | |
|
155 (1 << Registers::s7); |
|
156 |
|
157 static const uint32_t WrapperMask = |
|
158 VolatileMask | // = arguments |
|
159 (1 << Registers::t0) | // = outReg |
|
160 (1 << Registers::t1); // = argBase |
|
161 |
|
162 static const uint32_t NonAllocatableMask = |
|
163 (1 << Registers::zero) | |
|
164 (1 << Registers::at) | // at = scratch |
|
165 (1 << Registers::t8) | // t8 = scratch |
|
166 (1 << Registers::t9) | // t9 = scratch |
|
167 (1 << Registers::k0) | |
|
168 (1 << Registers::k1) | |
|
169 (1 << Registers::gp) | |
|
170 (1 << Registers::sp) | |
|
171 (1 << Registers::fp) | |
|
172 (1 << Registers::ra); |
|
173 |
|
174 // Registers that can be allocated without being saved, generally. |
|
175 static const uint32_t TempMask = VolatileMask & ~NonAllocatableMask; |
|
176 |
|
177 // Registers returned from a JS -> JS call. |
|
178 static const uint32_t JSCallMask = |
|
179 (1 << Registers::v0) | |
|
180 (1 << Registers::v1); |
|
181 |
|
182 // Registers returned from a JS -> C call. |
|
183 static const uint32_t CallMask = |
|
184 (1 << Registers::v0) | |
|
185 (1 << Registers::v1); // used for double-size returns |
|
186 |
|
187 static const uint32_t AllocatableMask = AllMask & ~NonAllocatableMask; |
|
188 }; |
|
189 |
|
190 // Smallest integer type that can hold a register bitmask. |
|
191 typedef uint32_t PackedRegisterMask; |
|
192 |
|
193 |
|
194 // MIPS32 can have two types of floating-point coprocessors: |
|
195 // - 32 bit floating-point coprocessor - In this case, there are 32 single |
|
196 // precision registers and pairs of even and odd float registers are used as |
|
197 // double precision registers. Example: f0 (double) is composed of |
|
198 // f0 and f1 (single). |
|
199 // - 64 bit floating-point coprocessor - In this case, there are 32 double |
|
200 // precision register which can also be used as single precision registers. |
|
201 |
|
202 // When using O32 ABI, floating-point coprocessor is 32 bit |
|
203 // When using N32 ABI, floating-point coprocessor is 64 bit. |
|
204 class FloatRegisters |
|
205 { |
|
206 public: |
|
207 enum FPRegisterID { |
|
208 f0 = 0, |
|
209 f1, |
|
210 f2, |
|
211 f3, |
|
212 f4, |
|
213 f5, |
|
214 f6, |
|
215 f7, |
|
216 f8, |
|
217 f9, |
|
218 f10, |
|
219 f11, |
|
220 f12, |
|
221 f13, |
|
222 f14, |
|
223 f15, |
|
224 f16, |
|
225 f17, |
|
226 f18, |
|
227 f19, |
|
228 f20, |
|
229 f21, |
|
230 f22, |
|
231 f23, |
|
232 f24, |
|
233 f25, |
|
234 f26, |
|
235 f27, |
|
236 f28, |
|
237 f29, |
|
238 f30, |
|
239 f31, |
|
240 invalid_freg |
|
241 }; |
|
242 typedef FPRegisterID Code; |
|
243 |
|
244 static const char *GetName(Code code) { |
|
245 static const char * const Names[] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
|
246 "f8", "f9", "f10", "f11", "f12", "f13", |
|
247 "f14", "f15", "f16", "f17", "f18", "f19", |
|
248 "f20", "f21", "f22", "f23", "f24", "f25", |
|
249 "f26", "f27", "f28", "f29", "f30", "f31"}; |
|
250 return Names[code]; |
|
251 } |
|
252 static const char *GetName(uint32_t i) { |
|
253 JS_ASSERT(i < Total); |
|
254 return GetName(Code(i)); |
|
255 } |
|
256 |
|
257 static Code FromName(const char *name); |
|
258 |
|
259 static const Code Invalid = invalid_freg; |
|
260 |
|
261 static const uint32_t Total = 32; |
|
262 // :TODO: (Bug 972836) // Fix this once odd regs can be used as float32 |
|
263 // only. For now we don't allocate odd regs for O32 ABI. |
|
264 static const uint32_t Allocatable = 14; |
|
265 |
|
266 static const uint32_t AllMask = 0xffffffff; |
|
267 |
|
268 static const uint32_t VolatileMask = |
|
269 (1 << FloatRegisters::f0) | |
|
270 (1 << FloatRegisters::f2) | |
|
271 (1 << FloatRegisters::f4) | |
|
272 (1 << FloatRegisters::f6) | |
|
273 (1 << FloatRegisters::f8) | |
|
274 (1 << FloatRegisters::f10) | |
|
275 (1 << FloatRegisters::f12) | |
|
276 (1 << FloatRegisters::f14) | |
|
277 (1 << FloatRegisters::f16) | |
|
278 (1 << FloatRegisters::f18); |
|
279 static const uint32_t NonVolatileMask = |
|
280 (1 << FloatRegisters::f20) | |
|
281 (1 << FloatRegisters::f22) | |
|
282 (1 << FloatRegisters::f24) | |
|
283 (1 << FloatRegisters::f26) | |
|
284 (1 << FloatRegisters::f28) | |
|
285 (1 << FloatRegisters::f30); |
|
286 |
|
287 static const uint32_t WrapperMask = VolatileMask; |
|
288 |
|
289 // :TODO: (Bug 972836) // Fix this once odd regs can be used as float32 |
|
290 // only. For now we don't allocate odd regs for O32 ABI. |
|
291 static const uint32_t NonAllocatableMask = |
|
292 (1 << FloatRegisters::f1) | |
|
293 (1 << FloatRegisters::f3) | |
|
294 (1 << FloatRegisters::f5) | |
|
295 (1 << FloatRegisters::f7) | |
|
296 (1 << FloatRegisters::f9) | |
|
297 (1 << FloatRegisters::f11) | |
|
298 (1 << FloatRegisters::f13) | |
|
299 (1 << FloatRegisters::f15) | |
|
300 (1 << FloatRegisters::f17) | |
|
301 (1 << FloatRegisters::f19) | |
|
302 (1 << FloatRegisters::f21) | |
|
303 (1 << FloatRegisters::f23) | |
|
304 (1 << FloatRegisters::f25) | |
|
305 (1 << FloatRegisters::f27) | |
|
306 (1 << FloatRegisters::f29) | |
|
307 (1 << FloatRegisters::f31) | |
|
308 // f18 and f16 are MIPS scratch float registers. |
|
309 (1 << FloatRegisters::f16) | |
|
310 (1 << FloatRegisters::f18); |
|
311 |
|
312 // Registers that can be allocated without being saved, generally. |
|
313 static const uint32_t TempMask = VolatileMask & ~NonAllocatableMask; |
|
314 |
|
315 static const uint32_t AllocatableMask = AllMask & ~NonAllocatableMask; |
|
316 }; |
|
317 |
|
318 uint32_t GetMIPSFlags(); |
|
319 bool hasFPU(); |
|
320 |
|
321 } // namespace jit |
|
322 } // namespace js |
|
323 |
|
324 #endif /* jit_mips_Architecture_mips_h */ |