cpp: Use #pragma once instead of #ifndef guards
[ghc.git] / includes / stg / Regs.h
1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 1998-2012
4 *
5 * Registers in the STG machine.
6 *
7 * Do not #include this file directly: #include "Rts.h" instead.
8 *
9 * To understand the structure of the RTS headers, see the wiki:
10 * http://ghc.haskell.org/trac/ghc/wiki/Commentary/SourceTree/Includes
11 *
12 * ---------------------------------------------------------------------------*/
13
14 #pragma once
15
16 /*
17 * The STG machine has a collection of "registers", each one of which
18 * may or may not correspond to an actual machine register when
19 * running code.
20 *
21 * The register set is backed by a table in memory (struct
22 * StgRegTable). If a particular STG register is not mapped to a
23 * machine register, then the appropriate slot in this table is used
24 * instead.
25 *
26 * This table is itself pointed to by another register, BaseReg. If
27 * BaseReg is not in a machine register, then the register table is
28 * used from an absolute location (MainCapability).
29 *
30 */
31
32 typedef struct {
33 StgWord stgEagerBlackholeInfo;
34 StgFunPtr stgGCEnter1;
35 StgFunPtr stgGCFun;
36 } StgFunTable;
37
38 /*
39 * Vanilla registers are given this union type, which is purely so
40 * that we can cast the vanilla reg to a variety of types with the
41 * minimum of syntax. eg. R1.w instead of (StgWord)R1.
42 */
43 typedef union {
44 StgWord w;
45 StgAddr a;
46 StgChar c;
47 StgFloat f;
48 StgInt i;
49 StgPtr p;
50 } StgUnion;
51
52 /*
53 * This is the table that holds shadow-locations for all the STG
54 * registers. The shadow locations are used when:
55 *
56 * 1) the particular register isn't mapped to a real machine
57 * register, probably because there's a shortage of real registers.
58 * 2) caller-saves registers are saved across a CCall
59 */
60 typedef struct {
61 StgUnion rR1;
62 StgUnion rR2;
63 StgUnion rR3;
64 StgUnion rR4;
65 StgUnion rR5;
66 StgUnion rR6;
67 StgUnion rR7;
68 StgUnion rR8;
69 StgUnion rR9; /* used occasionally by heap/stack checks */
70 StgUnion rR10; /* used occasionally by heap/stack checks */
71 StgFloat rF1;
72 StgFloat rF2;
73 StgFloat rF3;
74 StgFloat rF4;
75 StgFloat rF5;
76 StgFloat rF6;
77 StgDouble rD1;
78 StgDouble rD2;
79 StgDouble rD3;
80 StgDouble rD4;
81 StgDouble rD5;
82 StgDouble rD6;
83 StgWord128 rXMM1;
84 StgWord128 rXMM2;
85 StgWord128 rXMM3;
86 StgWord128 rXMM4;
87 StgWord128 rXMM5;
88 StgWord128 rXMM6;
89 StgWord256 rYMM1;
90 StgWord256 rYMM2;
91 StgWord256 rYMM3;
92 StgWord256 rYMM4;
93 StgWord256 rYMM5;
94 StgWord256 rYMM6;
95 StgWord512 rZMM1;
96 StgWord512 rZMM2;
97 StgWord512 rZMM3;
98 StgWord512 rZMM4;
99 StgWord512 rZMM5;
100 StgWord512 rZMM6;
101 StgWord64 rL1;
102 StgPtr rSp;
103 StgPtr rSpLim;
104 StgPtr rHp;
105 StgPtr rHpLim;
106 struct CostCentreStack_ * rCCCS; /* current cost-centre-stack */
107 struct StgTSO_ * rCurrentTSO;
108 struct nursery_ * rNursery;
109 struct bdescr_ * rCurrentNursery; /* Hp/HpLim point into this block */
110 struct bdescr_ * rCurrentAlloc; /* for allocation using allocate() */
111 StgWord rHpAlloc; /* number of *bytes* being allocated in heap */
112 StgWord rRet; /* holds the return code of the thread */
113 } StgRegTable;
114
115 #if IN_STG_CODE
116
117 /*
118 * Registers Hp and HpLim are global across the entire system, and are
119 * copied into the RegTable or registers before executing a thread.
120 *
121 * Registers Sp and SpLim are saved in the TSO for the thread, but are
122 * copied into the RegTable or registers before executing a thread.
123 *
124 * All other registers are "general purpose", and are used for passing
125 * arguments to functions, and returning values. The code generator
126 * knows how many of these are in real registers, and avoids
127 * generating code that uses non-real registers. General purpose
128 * registers are never saved when returning to the scheduler, instead
129 * we save whatever is live at the time on the stack, and restore it
130 * later. This should reduce the context switch time, amongst other
131 * things.
132 *
133 * For argument passing, the stack will be used in preference to
134 * pseudo-registers if the architecture has too few general purpose
135 * registers.
136 *
137 * Some special RTS functions like newArray and the Integer primitives
138 * expect their arguments to be in registers R1-Rn, so we use these
139 * (pseudo-)registers in those cases.
140 */
141
142 /* -----------------------------------------------------------------------------
143 * Emit the GCC-specific register declarations for each machine
144 * register being used. If any STG register isn't mapped to a machine
145 * register, then map it to an offset from BaseReg.
146 *
147 * First, the general purpose registers. The idea is, if a particular
148 * general-purpose STG register can't be mapped to a real machine
149 * register, it won't be used at all. Instead, we'll use the stack.
150 */
151
152 /* define NO_REGS to omit register declarations - used in RTS C code
153 * that needs all the STG definitions but not the global register
154 * settings.
155 */
156 #define GLOBAL_REG_DECL(type,name,reg) register type name REG(reg);
157
158 #if defined(REG_R1) && !defined(NO_GLOBAL_REG_DECLS)
159 GLOBAL_REG_DECL(StgUnion,R1,REG_R1)
160 #else
161 # define R1 (BaseReg->rR1)
162 #endif
163
164 #if defined(REG_R2) && !defined(NO_GLOBAL_REG_DECLS)
165 GLOBAL_REG_DECL(StgUnion,R2,REG_R2)
166 #else
167 # define R2 (BaseReg->rR2)
168 #endif
169
170 #if defined(REG_R3) && !defined(NO_GLOBAL_REG_DECLS)
171 GLOBAL_REG_DECL(StgUnion,R3,REG_R3)
172 #else
173 # define R3 (BaseReg->rR3)
174 #endif
175
176 #if defined(REG_R4) && !defined(NO_GLOBAL_REG_DECLS)
177 GLOBAL_REG_DECL(StgUnion,R4,REG_R4)
178 #else
179 # define R4 (BaseReg->rR4)
180 #endif
181
182 #if defined(REG_R5) && !defined(NO_GLOBAL_REG_DECLS)
183 GLOBAL_REG_DECL(StgUnion,R5,REG_R5)
184 #else
185 # define R5 (BaseReg->rR5)
186 #endif
187
188 #if defined(REG_R6) && !defined(NO_GLOBAL_REG_DECLS)
189 GLOBAL_REG_DECL(StgUnion,R6,REG_R6)
190 #else
191 # define R6 (BaseReg->rR6)
192 #endif
193
194 #if defined(REG_R7) && !defined(NO_GLOBAL_REG_DECLS)
195 GLOBAL_REG_DECL(StgUnion,R7,REG_R7)
196 #else
197 # define R7 (BaseReg->rR7)
198 #endif
199
200 #if defined(REG_R8) && !defined(NO_GLOBAL_REG_DECLS)
201 GLOBAL_REG_DECL(StgUnion,R8,REG_R8)
202 #else
203 # define R8 (BaseReg->rR8)
204 #endif
205
206 #if defined(REG_R9) && !defined(NO_GLOBAL_REG_DECLS)
207 GLOBAL_REG_DECL(StgUnion,R9,REG_R9)
208 #else
209 # define R9 (BaseReg->rR9)
210 #endif
211
212 #if defined(REG_R10) && !defined(NO_GLOBAL_REG_DECLS)
213 GLOBAL_REG_DECL(StgUnion,R10,REG_R10)
214 #else
215 # define R10 (BaseReg->rR10)
216 #endif
217
218 #if defined(REG_F1) && !defined(NO_GLOBAL_REG_DECLS)
219 GLOBAL_REG_DECL(StgFloat,F1,REG_F1)
220 #else
221 #define F1 (BaseReg->rF1)
222 #endif
223
224 #if defined(REG_F2) && !defined(NO_GLOBAL_REG_DECLS)
225 GLOBAL_REG_DECL(StgFloat,F2,REG_F2)
226 #else
227 #define F2 (BaseReg->rF2)
228 #endif
229
230 #if defined(REG_F3) && !defined(NO_GLOBAL_REG_DECLS)
231 GLOBAL_REG_DECL(StgFloat,F3,REG_F3)
232 #else
233 #define F3 (BaseReg->rF3)
234 #endif
235
236 #if defined(REG_F4) && !defined(NO_GLOBAL_REG_DECLS)
237 GLOBAL_REG_DECL(StgFloat,F4,REG_F4)
238 #else
239 #define F4 (BaseReg->rF4)
240 #endif
241
242 #if defined(REG_F5) && !defined(NO_GLOBAL_REG_DECLS)
243 GLOBAL_REG_DECL(StgFloat,F5,REG_F5)
244 #else
245 #define F5 (BaseReg->rF5)
246 #endif
247
248 #if defined(REG_F6) && !defined(NO_GLOBAL_REG_DECLS)
249 GLOBAL_REG_DECL(StgFloat,F6,REG_F6)
250 #else
251 #define F6 (BaseReg->rF6)
252 #endif
253
254 #if defined(REG_D1) && !defined(NO_GLOBAL_REG_DECLS)
255 GLOBAL_REG_DECL(StgDouble,D1,REG_D1)
256 #else
257 #define D1 (BaseReg->rD1)
258 #endif
259
260 #if defined(REG_D2) && !defined(NO_GLOBAL_REG_DECLS)
261 GLOBAL_REG_DECL(StgDouble,D2,REG_D2)
262 #else
263 #define D2 (BaseReg->rD2)
264 #endif
265
266 #if defined(REG_D3) && !defined(NO_GLOBAL_REG_DECLS)
267 GLOBAL_REG_DECL(StgDouble,D3,REG_D3)
268 #else
269 #define D3 (BaseReg->rD3)
270 #endif
271
272 #if defined(REG_D4) && !defined(NO_GLOBAL_REG_DECLS)
273 GLOBAL_REG_DECL(StgDouble,D4,REG_D4)
274 #else
275 #define D4 (BaseReg->rD4)
276 #endif
277
278 #if defined(REG_D5) && !defined(NO_GLOBAL_REG_DECLS)
279 GLOBAL_REG_DECL(StgDouble,D5,REG_D5)
280 #else
281 #define D5 (BaseReg->rD5)
282 #endif
283
284 #if defined(REG_D6) && !defined(NO_GLOBAL_REG_DECLS)
285 GLOBAL_REG_DECL(StgDouble,D6,REG_D6)
286 #else
287 #define D6 (BaseReg->rD6)
288 #endif
289
290 #if defined(REG_XMM1) && !defined(NO_GLOBAL_REG_DECLS)
291 GLOBAL_REG_DECL(StgWord128,XMM1,REG_XMM1)
292 #else
293 #define XMM1 (BaseReg->rXMM1)
294 #endif
295
296 #if defined(REG_XMM2) && !defined(NO_GLOBAL_REG_DECLS)
297 GLOBAL_REG_DECL(StgWord128,XMM2,REG_XMM2)
298 #else
299 #define XMM2 (BaseReg->rXMM2)
300 #endif
301
302 #if defined(REG_XMM3) && !defined(NO_GLOBAL_REG_DECLS)
303 GLOBAL_REG_DECL(StgWord128,XMM3,REG_XMM3)
304 #else
305 #define XMM3 (BaseReg->rXMM3)
306 #endif
307
308 #if defined(REG_XMM4) && !defined(NO_GLOBAL_REG_DECLS)
309 GLOBAL_REG_DECL(StgWord128,XMM4,REG_XMM4)
310 #else
311 #define XMM4 (BaseReg->rXMM4)
312 #endif
313
314 #if defined(REG_XMM5) && !defined(NO_GLOBAL_REG_DECLS)
315 GLOBAL_REG_DECL(StgWord128,XMM5,REG_XMM5)
316 #else
317 #define XMM5 (BaseReg->rXMM5)
318 #endif
319
320 #if defined(REG_XMM6) && !defined(NO_GLOBAL_REG_DECLS)
321 GLOBAL_REG_DECL(StgWord128,XMM6,REG_XMM6)
322 #else
323 #define XMM6 (BaseReg->rXMM6)
324 #endif
325
326 #if defined(REG_YMM1) && !defined(NO_GLOBAL_REG_DECLS)
327 GLOBAL_REG_DECL(StgWord256,YMM1,REG_YMM1)
328 #else
329 #define YMM1 (BaseReg->rYMM1)
330 #endif
331
332 #if defined(REG_YMM2) && !defined(NO_GLOBAL_REG_DECLS)
333 GLOBAL_REG_DECL(StgWord256,YMM2,REG_YMM2)
334 #else
335 #define YMM2 (BaseReg->rYMM2)
336 #endif
337
338 #if defined(REG_YMM3) && !defined(NO_GLOBAL_REG_DECLS)
339 GLOBAL_REG_DECL(StgWord256,YMM3,REG_YMM3)
340 #else
341 #define YMM3 (BaseReg->rYMM3)
342 #endif
343
344 #if defined(REG_YMM4) && !defined(NO_GLOBAL_REG_DECLS)
345 GLOBAL_REG_DECL(StgWord256,YMM4,REG_YMM4)
346 #else
347 #define YMM4 (BaseReg->rYMM4)
348 #endif
349
350 #if defined(REG_YMM5) && !defined(NO_GLOBAL_REG_DECLS)
351 GLOBAL_REG_DECL(StgWord256,YMM5,REG_YMM5)
352 #else
353 #define YMM5 (BaseReg->rYMM5)
354 #endif
355
356 #if defined(REG_YMM6) && !defined(NO_GLOBAL_REG_DECLS)
357 GLOBAL_REG_DECL(StgWord256,YMM6,REG_YMM6)
358 #else
359 #define YMM6 (BaseReg->rYMM6)
360 #endif
361
362 #if defined(REG_ZMM1) && !defined(NO_GLOBAL_REG_DECLS)
363 GLOBAL_REG_DECL(StgWord512,ZMM1,REG_ZMM1)
364 #else
365 #define ZMM1 (BaseReg->rZMM1)
366 #endif
367
368 #if defined(REG_ZMM2) && !defined(NO_GLOBAL_REG_DECLS)
369 GLOBAL_REG_DECL(StgWord512,ZMM2,REG_ZMM2)
370 #else
371 #define ZMM2 (BaseReg->rZMM2)
372 #endif
373
374 #if defined(REG_ZMM3) && !defined(NO_GLOBAL_REG_DECLS)
375 GLOBAL_REG_DECL(StgWord512,ZMM3,REG_ZMM3)
376 #else
377 #define ZMM3 (BaseReg->rZMM3)
378 #endif
379
380 #if defined(REG_ZMM4) && !defined(NO_GLOBAL_REG_DECLS)
381 GLOBAL_REG_DECL(StgWord512,ZMM4,REG_ZMM4)
382 #else
383 #define ZMM4 (BaseReg->rZMM4)
384 #endif
385
386 #if defined(REG_ZMM5) && !defined(NO_GLOBAL_REG_DECLS)
387 GLOBAL_REG_DECL(StgWord512,ZMM5,REG_ZMM5)
388 #else
389 #define ZMM5 (BaseReg->rZMM5)
390 #endif
391
392 #if defined(REG_ZMM6) && !defined(NO_GLOBAL_REG_DECLS)
393 GLOBAL_REG_DECL(StgWord512,ZMM6,REG_ZMM6)
394 #else
395 #define ZMM6 (BaseReg->rZMM6)
396 #endif
397
398 #if defined(REG_L1) && !defined(NO_GLOBAL_REG_DECLS)
399 GLOBAL_REG_DECL(StgWord64,L1,REG_L1)
400 #else
401 #define L1 (BaseReg->rL1)
402 #endif
403
404 /*
405 * If BaseReg isn't mapped to a machine register, just use the global
406 * address of the current register table (CurrentRegTable in
407 * concurrent Haskell, MainRegTable otherwise).
408 */
409
410 /* A capability is a combination of a FunTable and a RegTable. In STG
411 * code, BaseReg normally points to the RegTable portion of this
412 * structure, so that we can index both forwards and backwards to take
413 * advantage of shorter instruction forms on some archs (eg. x86).
414 * This is a cut-down version of the Capability structure; the full
415 * version is defined in Capability.h.
416 */
417 struct PartCapability_ {
418 StgFunTable f;
419 StgRegTable r;
420 };
421
422 /* No such thing as a MainCapability under THREADED_RTS - each thread must have
423 * its own Capability.
424 */
425 #if IN_STG_CODE && !(defined(THREADED_RTS) && !defined(NOSMP))
426 extern W_ MainCapability[];
427 #endif
428
429 /*
430 * Assigning to BaseReg (the ASSIGN_BaseReg macro): this happens on
431 * return from a "safe" foreign call, when the thread might be running
432 * on a new Capability. Obviously if BaseReg is not a register, then
433 * we are restricted to a single Capability (this invariant is enforced
434 * in Capability.c:initCapabilities), and assigning to BaseReg can be omitted.
435 */
436
437 #if defined(REG_Base) && !defined(NO_GLOBAL_REG_DECLS)
438 GLOBAL_REG_DECL(StgRegTable *,BaseReg,REG_Base)
439 #define ASSIGN_BaseReg(e) (BaseReg = (e))
440 #else
441 #if defined(THREADED_RTS) && !defined(NOSMP)
442 #error BaseReg must be in a register for THREADED_RTS
443 #endif
444 #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
445 #define ASSIGN_BaseReg(e) (e)
446 #endif
447
448 #if defined(REG_Sp) && !defined(NO_GLOBAL_REG_DECLS)
449 GLOBAL_REG_DECL(P_,Sp,REG_Sp)
450 #else
451 #define Sp (BaseReg->rSp)
452 #endif
453
454 #if defined(REG_SpLim) && !defined(NO_GLOBAL_REG_DECLS)
455 GLOBAL_REG_DECL(P_,SpLim,REG_SpLim)
456 #else
457 #define SpLim (BaseReg->rSpLim)
458 #endif
459
460 #if defined(REG_Hp) && !defined(NO_GLOBAL_REG_DECLS)
461 GLOBAL_REG_DECL(P_,Hp,REG_Hp)
462 #else
463 #define Hp (BaseReg->rHp)
464 #endif
465
466 #if defined(REG_HpLim) && !defined(NO_GLOBAL_REG_DECLS)
467 #error HpLim cannot be in a register
468 #else
469 #define HpLim (BaseReg->rHpLim)
470 #endif
471
472 #if defined(REG_CCCS) && !defined(NO_GLOBAL_REG_DECLS)
473 GLOBAL_REG_DECL(struct CostCentreStack_ *,CCCS,REG_CCCS)
474 #else
475 #define CCCS (BaseReg->rCCCS)
476 #endif
477
478 #if defined(REG_CurrentTSO) && !defined(NO_GLOBAL_REG_DECLS)
479 GLOBAL_REG_DECL(struct _StgTSO *,CurrentTSO,REG_CurrentTSO)
480 #else
481 #define CurrentTSO (BaseReg->rCurrentTSO)
482 #endif
483
484 #if defined(REG_CurrentNursery) && !defined(NO_GLOBAL_REG_DECLS)
485 GLOBAL_REG_DECL(bdescr *,CurrentNursery,REG_CurrentNursery)
486 #else
487 #define CurrentNursery (BaseReg->rCurrentNursery)
488 #endif
489
490 #if defined(REG_HpAlloc) && !defined(NO_GLOBAL_REG_DECLS)
491 GLOBAL_REG_DECL(bdescr *,HpAlloc,REG_HpAlloc)
492 #else
493 #define HpAlloc (BaseReg->rHpAlloc)
494 #endif
495
496 /* -----------------------------------------------------------------------------
497 Get absolute function pointers from the register table, to save
498 code space. On x86,
499
500 jmp *-12(%ebx)
501
502 is shorter than
503
504 jmp absolute_address
505
506 as long as the offset is within the range of a signed byte
507 (-128..+127). So we pick some common absolute_addresses and put
508 them in the register table. As a bonus, linking time should also
509 be reduced.
510
511 Other possible candidates in order of importance:
512
513 stg_upd_frame_info
514 stg_CAF_BLACKHOLE_info
515 stg_IND_STATIC_info
516
517 anything else probably isn't worth the effort.
518
519 -------------------------------------------------------------------------- */
520
521
522 #define FunReg ((StgFunTable *)((void *)BaseReg - STG_FIELD_OFFSET(struct PartCapability_, r)))
523
524 #define stg_EAGER_BLACKHOLE_info (FunReg->stgEagerBlackholeInfo)
525 #define stg_gc_enter_1 (FunReg->stgGCEnter1)
526 #define stg_gc_fun (FunReg->stgGCFun)
527
528 #endif /* IN_STG_CODE */