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 * https://gitlab.haskell.org/ghc/ghc/wikis/commentary/source-tree/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 */ 529