1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
|
%
% (c) The GRASP Project, Glasgow University, 1993
%
\section[StgRegs-decls]{STG-machine register mappings}
\begin{code}
#ifndef COPTREGS_H
#define COPTREGS_H
#include "StgMachDeps.h"
#include "StgTypes.h"
#include "MachRegs.h"
#define GLOBAL_REG_DECL(type,name,reg) register type name REG(reg);
\end{code}
Various parts of the GHC system use various sets of ``registers,'' by
which we mean (frequently-used) words of globally-visible information.
For example, the everyday ``Haskell threaded world,'' uses the
``registers'' @Hp@, @R4@, etc., etc.
We would really like to ``steal'' machine registers from the C
execution model (via GCC's global-variable-in-register extension) and
map some/all of our ``STG registers'' onto real machine registers.
This has a profound benefit in terms of execution speed.
This file/document/section sets out the various (machine-dependent)
mappings that we use.
Note: for one machine, there are {\em several} possible register
mappings, {\em one} of which is in force at any time. Obviously, the
``main'' mapping (used in the Haskell threaded world) dominates, but
when garbage-collecting (for example), we'd rather not tie up all
those registers in that way (i.e., for global-variables that aren't
used in the GC). Instead, we'd rather bring in {\em another} register
mapping, tuned to the needs of a particular (isolated) bit of C code.
As there are several garbage collectors there are quite a few possible
mappings.
%************************************************************************
%* *
\subsection[saved-STG-regs]{Saved STG registers}
%* *
%************************************************************************
The following stuff is available regardless of register map. It allows
us access to the saved STG registers from other parts of the RTS (notably
from the storage manager).
\begin{code}
typedef struct rt {
StgDouble rDbl[2]; /* Put a double first to ensure expected alignment */
StgFloat rFlt[4];
StgUnion rR[8];
PP_ rSpA;
PP_ rSuA;
P_ rSpB;
P_ rSuB;
P_ rHp;
P_ rHpLim;
I_ rTag;
StgRetAddr rRet;
I_ rActivity; /* NB: UNUSED */
P_ rCstkptr; /* used for iX86 registerizing only! offset=100 */
P_ rWrapReturn; /* ditto; offset=104 */
P_ rSaveECX; /* ditto; offset=108 */
#if defined(CONCURRENT)
P_ rStkO;
I_ rLiveness;
#endif
} STGRegisterTable;
\end{code}
There are several confusing macro sets for accessing STG registers at various
stages in their lives.
The MAIN_* macros refer to the save locations for the main thread.
These are generally useful when the main thread is suspended. Note
that the save locations for S[up][AB] are actually in the pseudo stack
object, MainStkO, when running threads.
The SAVE_* macros refer to the save locations for the current thread,
without using BaseReg. These are used when we cannot be sure that any
STG registers are actually loaded in machine registers.
The RTBL_* macros refer to the register table locations for the current
thread, indexed from BaseReg. If BaseReg is in a machine register, that
register {\em must} be loaded with the address of the register table.
OK, now... In the sequential world at least, each of those
``register'' declarations also set up a ``backup'' location; for
register @r@, the backup location (a global variable) is @r_SAVE@.
We need @SAVE_STG_REGS@ and @RESTORE_STG_REGS@ macros, which copy back
and forth between the ``registers'' and their \tr{*_SAVE} backup
locations.
In the parallel world, we have the closely-related business of
saving/restoring ``thread state''. We do it in two stages:
save/restore to/from \tr{*_SAVE} locations, then fill in the
``thread-state object'' (TSO) from the \tr{*_SAVE} locations. (This
means the thread-state saving can more easily be written in C, rather
than assembler.)
Why no space to save BaseReg? Because either (1) if in a caller-save
register, the caller will have saved it; or (2) if in a callee-save
register, the miniInterpret machinery will have saved it. This works
because we entered ``threaded Haskell land'' in a v disciplined
way---i.e., via miniInterpret.
However, the bits of code that use the various GC register maps (SCAV,
MARK, SCAN) are called in less-disciplined ways, so their base-regs
need saving/restoring. (WDP 95/02)
\begin{code}
#ifndef PAR
extern STGRegisterTable MainRegTable;
#endif /* PAR */
/* these are for the main register table */
#define MAIN_R1 (MainRegTable.rR[0])
#define MAIN_R2 (MainRegTable.rR[1])
#define MAIN_R3 (MainRegTable.rR[2])
#define MAIN_R4 (MainRegTable.rR[3])
#define MAIN_R5 (MainRegTable.rR[4])
#define MAIN_R6 (MainRegTable.rR[5])
#define MAIN_R7 (MainRegTable.rR[6])
#define MAIN_R8 (MainRegTable.rR[7])
#define MAIN_Flt1 (MainRegTable.rFlt[0])
#define MAIN_Flt2 (MainRegTable.rFlt[1])
#define MAIN_Flt3 (MainRegTable.rFlt[2])
#define MAIN_Flt4 (MainRegTable.rFlt[3])
#define MAIN_Dbl1 (MainRegTable.rDbl[0])
#define MAIN_Dbl2 (MainRegTable.rDbl[1])
#define MAIN_Hp (MainRegTable.rHp)
#define MAIN_HpLim (MainRegTable.rHpLim)
#define MAIN_Tag (MainRegTable.rTag)
#define MAIN_Ret (MainRegTable.rRet)
#define MAIN_StkO (MainStkO)
#define MAIN_Liveness (MainRegTable.rLiveness)
#ifndef CONCURRENT
#define MAIN_SpA (MainRegTable.rSpA)
#define MAIN_SuA (MainRegTable.rSuA)
#define MAIN_SpB (MainRegTable.rSpB)
#define MAIN_SuB (MainRegTable.rSuB)
/* these are really for *SAVE*ing */
#define SAVE_R1 MAIN_R1
#define SAVE_R2 MAIN_R2
#define SAVE_R3 MAIN_R3
#define SAVE_R4 MAIN_R4
#define SAVE_R5 MAIN_R5
#define SAVE_R6 MAIN_R6
#define SAVE_R7 MAIN_R7
#define SAVE_R8 MAIN_R8
#define SAVE_Flt1 MAIN_Flt1
#define SAVE_Flt2 MAIN_Flt2
#define SAVE_Flt3 MAIN_Flt3
#define SAVE_Flt4 MAIN_Flt4
#define SAVE_Dbl1 MAIN_Dbl1
#define SAVE_Dbl2 MAIN_Dbl2
#define SAVE_SpA MAIN_SpA
#define SAVE_SuA MAIN_SuA
#define SAVE_SpB MAIN_SpB
#define SAVE_SuB MAIN_SuB
#define SAVE_Tag MAIN_Tag
#define SAVE_Ret MAIN_Ret
#else
extern P_ MainStkO;
#define MAIN_SpA (STKO_SpA(MainStkO))
#define MAIN_SuA (STKO_SuA(MainStkO))
#define MAIN_SpB (STKO_SpB(MainStkO))
#define MAIN_SuB (STKO_SuB(MainStkO))
extern STGRegisterTable *CurrentRegTable;
/* these are really for *SAVE*ing */
#define SAVE_R1 (CurrentRegTable->rR[0])
#define SAVE_R2 (CurrentRegTable->rR[1])
#define SAVE_R3 (CurrentRegTable->rR[2])
#define SAVE_R4 (CurrentRegTable->rR[3])
#define SAVE_R5 (CurrentRegTable->rR[4])
#define SAVE_R6 (CurrentRegTable->rR[5])
#define SAVE_R7 (CurrentRegTable->rR[6])
#define SAVE_R8 (CurrentRegTable->rR[7])
#define SAVE_Flt1 (CurrentRegTable->rFlt[0])
#define SAVE_Flt2 (CurrentRegTable->rFlt[1])
#define SAVE_Flt3 (CurrentRegTable->rFlt[2])
#define SAVE_Flt4 (CurrentRegTable->rFlt[3])
#define SAVE_Dbl1 (CurrentRegTable->rDbl[0])
#define SAVE_Dbl2 (CurrentRegTable->rDbl[1])
/* These are only valid when StkOReg is loaded! */
#define SAVE_SpA (STKO_SpA(StkOReg))
#define SAVE_SuA (STKO_SuA(StkOReg))
#define SAVE_SpB (STKO_SpB(StkOReg))
#define SAVE_SuB (STKO_SuB(StkOReg))
#define SAVE_Tag (CurrentRegTable->rTag)
#define SAVE_Ret (CurrentRegTable->rRet)
#define SAVE_StkO (CurrentRegTable->rStkO)
#define SAVE_Liveness (CurrentRegTable->rLiveness)
#endif /* CONCURRENT */
/* Note that the SAVE_ locations for the Hp registers are in the smInfo structure */
#define SAVE_Hp (StorageMgrInfo.hp)
#define SAVE_HpLim (StorageMgrInfo.hplim)
\end{code}
%************************************************************************
%* *
\subsection[null-mapping-StgRegs]{The empty register mapping}
%* *
%************************************************************************
This mapping leaves all machine registers free for normal C allocation.
In the RTS, this is the preferred mapping, because it allows gcc to use
all available registers, with the normal callee-saves conventions.
\begin{code}
#if defined(NULL_REG_MAP)
#else
\end{code}
This is a HACK here; see comment in COptJumps.lh.
\begin{code}
#if alpha_dec_osf1_TARGET && defined(__STG_TAILJUMPS__) && defined(__GNUC__)
register void *_procedure __asm__("$27");
#endif
#if (mipsel_TARGET_ARCH || mipseb_TARGET_ARCH) && defined(__STG_TAILJUMPS__) && defined(__GNUC__)
register void *_procedure __asm__("$25");
#endif
\end{code}
%************************************************************************
%* *
\subsection[mark-mapping-StgRegs]{The ``mark'' register mapping}
%* *
%************************************************************************
The mark mapping is used for pointer-reversal marking during GC. It
is used by most of the current garbage collectors.
\begin{code}
#if defined(MARK_REG_MAP)
\end{code}
Mark (GC) register mapping:
\begin{verbatim}
sparc m68k alpha mipseX hppa iX86 powerpc
----- ---- ----- ------ ---- ---- -------
MarkBase ebx
Mark i0 a2 $9 $16 r4 ebp
MStack i1 a3 $10 $17 r5 esi
MRoot i2 a4 $11 $18 r6 edi
BitArray i3 a5 $12 $19 r7
HeapBase i4 d3 $13 $20 r8
HeapLim i5 d4 $14 $21 r9
\end{verbatim}
\begin{code}
typedef struct {
P_ rMark;
P_ rMStack;
P_ rMRoot;
BitWord *rBitArray;
P_ rHeapBase;
P_ rHeapLim;
P_ rMarkBase;
} RegisterTable;
#define REGDUMP(dump) static RegisterTable dump
#define SAVE_Mark (MarkRegTable.rMark)
#define SAVE_MStack (MarkRegTable.rMStack)
#define SAVE_MRoot (MarkRegTable.rMRoot)
#define SAVE_BitArray (MarkRegTable.rBitArray)
#define SAVE_HeapBase (MarkRegTable.rHeapBase)
#define SAVE_HeapLim (MarkRegTable.rHeapLim)
extern RegisterTable MarkRegTable;
#ifdef REG_MarkBase
GLOBAL_REG_DECL(RegisterTable *,MarkBaseReg,REG_MarkBase)
#else
#define MarkBaseReg (&MarkRegTable)
#endif
#ifdef REG_Mark
GLOBAL_REG_DECL(P_,Mark,REG_Mark)
#else
#define Mark SAVE_Mark
#endif
#ifdef REG_MStack
GLOBAL_REG_DECL(P_,MStack,REG_MStack)
#else
#define MStack SAVE_MStack
#endif
#ifdef REG_MRoot
GLOBAL_REG_DECL(P_,MRoot,REG_MRoot)
#else
#define MRoot SAVE_MRoot
#endif
#ifdef REG_BitArray
GLOBAL_REG_DECL(P_,BitArray,REG_BitArray)
#else
#define BitArray SAVE_BitArray
#endif
#ifdef REG_HeapBase
GLOBAL_REG_DECL(P_,HeapBase,REG_HeapBase)
#else
#define HeapBase SAVE_HeapBase
#endif
#ifdef REG_HeapLim
GLOBAL_REG_DECL(P_,HeapLim,REG_HeapLim)
#else
#define HeapLim SAVE_HeapLim
#endif
#if defined(__STG_GCC_REGS__)
/* Keep -Wmissing-prototypes from complaining */
void SAVE_REGS PROTO((RegisterTable *dump));
void RESTORE_REGS PROTO((RegisterTable *dump));
extern STG_INLINE
void SAVE_REGS(dump)
RegisterTable *dump;
{
#ifdef REG_MarkBase
dump->rMarkBase = (P_) MarkBaseReg; /* save whatever is in it */
MarkBaseReg = dump; /* set it correctly */
#endif
#ifdef REG_Mark
dump->rMark = Mark;
#endif
#ifdef REG_MStack
dump->rMStack = MStack;
#endif
#ifdef REG_MRoot
dump->rMRoot = MRoot;
#endif
#ifdef REG_BitArray
dump->rBitArray = BitArray;
#endif
#ifdef REG_HeapBase
dump->rHeapBase = HeapBase;
#endif
#ifdef REG_HeapLim
dump->rHeapLim = HeapLim;
#endif
}
extern STG_INLINE
void RESTORE_REGS(dump)
RegisterTable *dump;
{
#ifdef REG_Mark
Mark = dump->rMark;
#endif
#ifdef REG_MStack
MStack = dump->rMStack;
#endif
#ifdef REG_MRoot
MRoot = dump->rMRoot;
#endif
#ifdef REG_BitArray
BitArray = dump->rBitArray;
#endif
#ifdef REG_HeapBase
HeapBase = dump->rHeapBase;
#endif
#ifdef REG_HeapLim
HeapLim = dump->rHeapLim;
#endif
#ifdef REG_MarkBase
MarkBaseReg = (RegisterTable *) dump->rMarkBase; /* restore to whatever it was */
#endif
}
#else
#define SAVE_REGS(dump)
#define RESTORE_REGS(dump)
#endif
\end{code}
%************************************************************************
%* *
\subsection[scan-mapping-StgRegs]{The ``scan'' register mapping}
%* *
%************************************************************************
The scan mapping is used for all of the in-place garbage collectors.
On architectures with register windows, like the SPARC, these must
reside in global registers, because the scan code is not threaded.
\begin{code}
#else
#if defined(SCAN_REG_MAP)
\end{code}
Scan (GC) register mapping:
\begin{verbatim}
sparc m68k alpha mipseX hppa iX86 powerpc
----- ---- ----- ------ ---- ---- -------
ScanBase g4
Scan a2 $9 $16 r4 ebx
New a3 $10 $17 r5 ebp
LinkLim a4 $11 $18 r6 esi
\end{verbatim}
\begin{code}
typedef struct {
P_ rScan;
P_ rNew;
P_ rLinkLim;
P_ rScanBase;
} RegisterTable;
#define REGDUMP(dump) static RegisterTable dump
#define SAVE_Scan (ScanRegTable.rScan)
#define SAVE_New (ScanRegTable.rNew)
#define SAVE_LinkLim (ScanRegTable.rLinkLim)
extern RegisterTable ScanRegTable;
#ifdef REG_ScanBase
GLOBAL_REG_DECL(RegisterTable *,ScanBaseReg,REG_ScanBase)
#else
#define ScanBaseReg (&ScanRegTable)
#endif
#ifdef REG_Scan
GLOBAL_REG_DECL(P_,Scan,REG_Scan)
#else
# ifdef REG_ScanBase
# define Scan (ScanBaseReg->rScan)
# else
# define Scan SAVE_Scan
# endif
#endif
#ifdef REG_New
GLOBAL_REG_DECL(P_,New,REG_New)
#else
# ifdef REG_ScanBase
# define New (ScanBaseReg->rNew)
# else
# define New SAVE_New
# endif
#endif
#ifdef REG_LinkLim
GLOBAL_REG_DECL(P_,LinkLim,REG_LinkLim)
#else
# ifdef REG_ScanBase
# define LinkLim (ScanBaseReg->rLinkLim)
# else
# define LinkLim SAVE_LinkLim
# endif
#endif
#if defined(__STG_GCC_REGS__)
/* Keep -Wmissing-prototypes from complaining */
void SAVE_REGS PROTO((RegisterTable *dump));
void RESTORE_REGS PROTO((RegisterTable *dump));
extern STG_INLINE
void SAVE_REGS(dump)
RegisterTable *dump;
{
#ifdef REG_ScanBase
dump->rScanBase = (P_) ScanBaseReg; /* save whatever is in it */
ScanBaseReg = dump; /* set it correctly */
#endif
#ifdef REG_Scan
dump->rScan = Scan;
#endif
#ifdef REG_New
dump->rNew = New;
#endif
#ifdef REG_LinkLim
dump->rLinkLim = LinkLim;
#endif
}
extern STG_INLINE
void RESTORE_REGS(dump)
RegisterTable *dump;
{
#ifdef REG_Scan
Scan = dump->rScan;
#endif
#ifdef REG_New
New = dump->rNew;
#endif
#ifdef REG_LinkLim
LinkLim = dump->rLinkLim;
#endif
#ifdef REG_ScanBase
ScanBaseReg = (RegisterTable *) dump->rScanBase; /* restore to whatever it was */
#endif
}
#else
#define SAVE_REGS(dump)
#define RESTORE_REGS(dump)
#endif
\end{code}
%************************************************************************
%* *
\subsection[scav-mapping-StgRegs]{The ``scavenge'' register mapping}
%* *
%************************************************************************
The scan mapping is used for all of the in-place garbage collectors.
(I believe that it must use a subset of the registers that are used
in the mark mapping, but I could be wrong. --JSM)
Note: registers must not be mangled by sliding register windows,
etc. or there'll be trouble. ADR
\begin{code}
#else
#if defined(SCAV_REG_MAP)
\end{code}
Scavenge (GC) register mapping:
\begin{verbatim}
sparc m68k alpha mipseX hppa iX86 powerpc
----- ---- ----- ------ ---- ---- -------
ScavBase g4
Scav a2 $9 $16 r4 ebx
ToHp a3 $10 $17 r5 ebp
OldGen (gn/ap) a4 $11 $18 r6 esi
AllocGen (gn) a5
OldHp (gn) d3
\end{verbatim}
(Calling this struct @ScavRegisterTable@ would make it possible for
@gdb@ to display it properly. At the moment, @gdb@ confuses it with
the scan register table etc. ADR )
\begin{code}
typedef struct {
P_ rScav;
P_ rToHp;
P_ rOldGen;
#ifdef GCgn
P_ rAllocGen;
P_ rOldHp;
#endif
P_ rScavBase;
} RegisterTable;
#define REGDUMP(dump) static RegisterTable dump
#define SAVE_Scav (ScavRegTable.rScav)
#define SAVE_ToHp (ScavRegTable.rToHp)
#define SAVE_OldGen (ScavRegTable.rOldGen)
#define SAVE_AllocGen (ScavRegTable.rAllocGen)
#define SAVE_OldHp (ScavRegTable.rOldHp)
extern RegisterTable ScavRegTable;
#ifdef REG_ScavBase
GLOBAL_REG_DECL(RegisterTable *,ScavBaseReg,REG_ScavBase)
#else
#define ScavBaseReg (&ScavRegTable)
#endif
#ifdef REG_Scav
GLOBAL_REG_DECL(P_,Scav,REG_Scav)
#else
# ifdef REG_ScavBase
# define Scav (ScavBaseReg->rScav)
# else
# define Scav SAVE_Scav
# endif
#endif
#ifdef REG_ToHp
GLOBAL_REG_DECL(P_,ToHp,REG_ToHp)
#else
# ifdef REG_ScavBase
# define ToHp (ScavBaseReg->rToHp)
# else
# define ToHp SAVE_ToHp
# endif
#endif
#ifdef REG_OldGen
GLOBAL_REG_DECL(P_,OldGen,REG_OldGen)
#else
# ifdef REG_ScavBase
# define OldGen (ScavBaseReg->rOldGen)
# else
# define OldGen SAVE_OldGen
# endif
#endif
#ifdef REG_AllocGen
GLOBAL_REG_DECL(P_,AllocGen,REG_AllocGen)
#else
# ifdef REG_ScavBase
# define AllocGen (ScavBaseReg->rAllocGen)
# else
# define AllocGen SAVE_AllocGen
# endif
#endif
#ifdef REG_OldHp
GLOBAL_REG_DECL(P_,OldHp,REG_OldHp)
#else
# ifdef REG_ScavBase
# define OldHp (ScavBaseReg->rOldHp)
# else
# define OldHp SAVE_OldHp
# endif
#endif
#if defined(__STG_GCC_REGS__)
/* Keep -Wmissing-prototypes from complaining */
void SAVE_REGS PROTO((RegisterTable *dump));
void RESTORE_REGS PROTO((RegisterTable *dump));
extern STG_INLINE
void SAVE_REGS(dump)
RegisterTable *dump;
{
#ifdef REG_ScavBase
dump->rScavBase = (P_) ScavBaseReg; /* save whatever is in it */
ScavBaseReg = dump; /* set it correctly */
#endif
#ifdef REG_Scav
dump->rScav = Scav;
#endif
#ifdef REG_ToHp
dump->rToHp = ToHp;
#endif
#ifdef REG_OldGen
dump->rOldGen = OldGen;
#endif
#ifdef REG_AllocGen
dump->rAllocGen = AllocGen;
#endif
#ifdef REG_OldHp
dump->rOldHp = OldHp;
#endif
}
extern STG_INLINE
void RESTORE_REGS(dump)
RegisterTable *dump;
{
#ifdef REG_Scav
Scav = dump->rScav;
#endif
#ifdef REG_ToHp
ToHp = dump->rToHp;
#endif
#ifdef REG_OldGen
OldGen = dump->rOldGen;
#endif
#ifdef REG_AllocGen
AllocGen = dump->rAllocGen;
#endif
#ifdef REG_OldHp
OldHp = dump->rOldHp;
#endif
#ifdef REG_ScavBase
ScavBaseReg = (RegisterTable *) dump->rScavBase; /* restore to whatever it was */
#endif
}
#else
#define SAVE_REGS(dump)
#define RESTORE_REGS(dump)
#endif
\end{code}
%************************************************************************
%* *
\subsection[main-mapping-StgRegs]{The main register mapping (Haskell threaded world)}
%* *
%************************************************************************
\begin{code}
#else /* For simplicity, the default is MAIN_REG_MAP (this one) */
\end{code}
Main register-mapping summary: (1)~Specific architecture's details are
given later. (2)~Entries marked \tr{!} are caller-saves registers
that {\em must be saved} across ccalls; those marked \tr{@} are
caller-saves registers that need {\em not} be saved; those marked
\tr{#} are caller-saves registers that need to be restored, but don't
need to be saved; the rest are callee-save registers (the best kind).
IF YOU CHANGE THIS TABLE, YOU MAY NEED TO CHANGE CallWrapper.s
(or equiv) and [who knows?] maybe something else. Check the
documentation in the porter's part of the installation guide.
\begin{verbatim}
sparc m68k alpha mipseX hppa iX86 powerpc
----- ---- ----- ------ ---- ---- -------
BaseReg# a5 ebx
StkOReg (CONCURRENT)
R1/Node l1 d7 $1! $9! %r11
R2 l2 d6 $2! $10! %r12
R3 l3 d5 $3! $11! %r13
R4 l4 $4! $12! %r14
R5 l5 $5! $13! %r15
R6 l6 $6! $14! %r16
R7 l7 $7! $15! %r17
R8 $8! $24! %r18
TagReg@
FltReg1 f2! fp2 $f1 $f20 %fr12
FltReg2 f3! fp3 $f2 $f22 %fr12R
FltReg3 f4! fp4 $f3 $f24 %fr13
FltReg4 f5! fp5 $f4 $f26 %fr13R
DblReg1 f6! fp6 $f5 $f28 %fr20 * SEE NOTES!
DblReg2 f8! fp7 $f6 $f30 %fr20 * SEE NOTES!
SpA i0 a3 $9 $16 %r4
SuA i1 d3 $10 $17 %r5
SpB i2 a4 $11 $18 %r6
SuB i3 d4 $12 $19 %r7
Hp i4 a2 $13 $20 %r8
HpLim i5 $14 $21 %r9
RetReg l0 $15 $22 %r10
Liveness (CONCURRENT)
StdUpdRetVec#
StkStub# i7 $23
\end{verbatim}
Notes:
\begin{enumerate}
\item
Registers not mentioned in the summary table end up in the default
(a memory location in @MainRegTable@).
\item
@BaseReg@ is in a machine register if anything is (well, unless everything is!)
It points to a block of memory in which the things which don't end up in machine
registers live.
\item
Exceptions to previous point:
If the following labels are in machine registers, then the
corresponding register name refers to what's in its register; otherwise,
it refers to the label:
\begin{verbatim}
StdUpdRetVecReg vtbl_StdUpdFrame
StkStubReg STK_STUB_closure
\end{verbatim}
Also, if TagReg is not in a machine register, its name refers to
@INFO_TAG(InfoPtr)@, the tag field from the info table pointed to by
register R2 (InfoPtr).
\end{enumerate}
Next, we have the code to declare the various global registers. Those
STG registers which don't actually live in machine registers are
defined as macros which refer to the registers as fixed offsets into
the register table. Note that the register table will contain blank
spots for the STG registers that reside in machine registers. Not to
worry; these blank spots will be filled in whenever the register
context is saved, so the space does not go to waste.
\begin{code}
#define Node (R1.p)
#define InfoPtr (R2.d)
/* these are if we get stuck using the reg-tbl "register" (no machine reg avail) */
#define RTBL_Dbl1 (BaseReg->rDbl[0])
#define RTBL_Dbl2 (BaseReg->rDbl[1])
#define RTBL_Flt1 (BaseReg->rFlt[0])
#define RTBL_Flt2 (BaseReg->rFlt[1])
#define RTBL_Flt3 (BaseReg->rFlt[2])
#define RTBL_Flt4 (BaseReg->rFlt[3])
#define RTBL_R1 (BaseReg->rR[0])
#define RTBL_R2 (BaseReg->rR[1])
#define RTBL_R3 (BaseReg->rR[2])
#define RTBL_R4 (BaseReg->rR[3])
#define RTBL_R5 (BaseReg->rR[4])
#define RTBL_R6 (BaseReg->rR[5])
#define RTBL_R7 (BaseReg->rR[6])
#define RTBL_R8 (BaseReg->rR[7])
#define RTBL_SpA (BaseReg->rSpA)
#define RTBL_SuA (BaseReg->rSuA)
#define RTBL_SpB (BaseReg->rSpB)
#define RTBL_SuB (BaseReg->rSuB)
#define RTBL_Hp (BaseReg->rHp)
#define RTBL_HpLim (BaseReg->rHpLim)
#define RTBL_Tag (BaseReg->rTag)
#define RTBL_Ret (BaseReg->rRet)
#define RTBL_StkO (BaseReg->rStkO)
#define RTBL_Liveness (BaseReg->rLiveness)
#ifdef REG_Base
GLOBAL_REG_DECL(STGRegisterTable *,BaseReg,REG_Base)
#else
#ifdef CONCURRENT
#define BaseReg CurrentRegTable
#else
#define BaseReg (&MainRegTable)
#endif /* CONCURRENT */
#endif /* REG_Base */
#ifdef REG_StkO
GLOBAL_REG_DECL(P_,StkOReg,REG_StkO)
#else
#define StkOReg RTBL_StkO
#endif
#ifndef __STG_REGS_AVAIL__ /* driver ensures it is 2 or more */
# define __STG_REGS_AVAIL__ 8 /* R1 to R8 */
/* this would only be non-8 if doing weird experiments (WDP 95/11) */
/* or it might be set lower for a particular arch... */
#endif
/* R1 is used for Node */
#ifdef REG_R1
GLOBAL_REG_DECL(StgUnion,R1,REG_R1)
#else
#define R1 RTBL_R1
#endif
/* R2 is used for InfoPtr */
#ifdef REG_R2
GLOBAL_REG_DECL(StgUnion,R2,REG_R2)
#else
#define R2 RTBL_R2
#endif
#ifdef REG_R3
GLOBAL_REG_DECL(StgUnion,R3,REG_R3)
#else
# define R3 RTBL_R3
#endif
#ifdef REG_R4
GLOBAL_REG_DECL(StgUnion,R4,REG_R4)
#else
# define R4 RTBL_R4
#endif
#ifdef REG_R5
GLOBAL_REG_DECL(StgUnion,R5,REG_R5)
#else
# define R5 RTBL_R5
#endif
#ifdef REG_R6
GLOBAL_REG_DECL(StgUnion,R6,REG_R6)
#else
# define R6 RTBL_R6
#endif
#ifdef REG_R7
GLOBAL_REG_DECL(StgUnion,R7,REG_R7)
#else
# define R7 RTBL_R7
#endif
#ifdef REG_R8
GLOBAL_REG_DECL(StgUnion,R8,REG_R8)
#else
# define R8 RTBL_R8
#endif
#ifdef REG_Flt1
GLOBAL_REG_DECL(StgFloat,FltReg1,REG_Flt1)
#else
#define FltReg1 RTBL_Flt1
#endif
#ifdef REG_Flt2
GLOBAL_REG_DECL(StgFloat,FltReg2,REG_Flt2)
#else
#define FltReg2 RTBL_Flt2
#endif
#ifdef REG_Flt3
GLOBAL_REG_DECL(StgFloat,FltReg3,REG_Flt3)
#else
#define FltReg3 RTBL_Flt3
#endif
#ifdef REG_Flt4
GLOBAL_REG_DECL(StgFloat,FltReg4,REG_Flt4)
#else
#define FltReg4 RTBL_Flt4
#endif
#ifdef REG_Dbl1
GLOBAL_REG_DECL(StgDouble,DblReg1,REG_Dbl1)
#else
#define DblReg1 RTBL_Dbl1
#endif
#ifdef REG_Dbl2
GLOBAL_REG_DECL(StgDouble,DblReg2,REG_Dbl2)
#else
#define DblReg2 RTBL_Dbl2
#endif
#ifdef REG_Tag
GLOBAL_REG_DECL(I_,TagReg,REG_Tag)
#define SET_TAG(tag) TagReg = tag
#else
#define TagReg INFO_TAG(InfoPtr)
#define SET_TAG(tag) /* nothing */
#endif
#ifdef REG_Ret
GLOBAL_REG_DECL(StgRetAddr,RetReg,REG_Ret)
#else
#define RetReg RTBL_Ret
#endif
#ifdef REG_SpA
GLOBAL_REG_DECL(PP_,SpA,REG_SpA)
#else
#define SpA RTBL_SpA
#endif
#ifdef REG_SuA
GLOBAL_REG_DECL(PP_,SuA,REG_SuA)
#else
#define SuA RTBL_SuA
#endif
#ifdef REG_SpB
GLOBAL_REG_DECL(P_,SpB,REG_SpB)
#else
#define SpB RTBL_SpB
#endif
#ifdef REG_SuB
GLOBAL_REG_DECL(P_,SuB,REG_SuB)
#else
#define SuB RTBL_SuB
#endif
#ifdef REG_Hp
GLOBAL_REG_DECL(P_,Hp,REG_Hp)
#else
#define Hp RTBL_Hp
#endif
#ifdef REG_HpLim
GLOBAL_REG_DECL(P_,HpLim,REG_HpLim)
#else
#define HpLim RTBL_HpLim
#endif
#ifdef REG_Liveness
GLOBAL_REG_DECL(I_,LivenessReg,REG_Liveness)
#else
#define LivenessReg RTBL_Liveness
#endif
#ifdef REG_StdUpdRetVec
GLOBAL_REG_DECL(D_,StdUpdRetVecReg,REG_StdUpdRetVec)
#else
#define StdUpdRetVecReg vtbl_StdUpdFrame
#endif
#ifdef REG_StkStub
GLOBAL_REG_DECL(P_,StkStubReg,REG_StkStub)
#else
#define StkStubReg STK_STUB_closure
#endif
#ifdef CALLER_SAVES_StkO
#define CALLER_SAVE_StkO SAVE_StkO = StkOReg;
#define CALLER_RESTORE_StkO StkOReg = SAVE_StkO;
#else
#define CALLER_SAVE_StkO /* nothing */
#define CALLER_RESTORE_StkO /* nothing */
#endif
#ifdef CALLER_SAVES_R1
#define CALLER_SAVE_R1 SAVE_R1 = R1;
#define CALLER_RESTORE_R1 R1 = SAVE_R1;
#else
#define CALLER_SAVE_R1 /* nothing */
#define CALLER_RESTORE_R1 /* nothing */
#endif
#ifdef CALLER_SAVES_R2
#define CALLER_SAVE_R2 SAVE_R2 = R2;
#define CALLER_RESTORE_R2 R2 = SAVE_R2;
#else
#define CALLER_SAVE_R2 /* nothing */
#define CALLER_RESTORE_R2 /* nothing */
#endif
#ifdef CALLER_SAVES_R3
#define CALLER_SAVE_R3 SAVE_R3 = R3;
#define CALLER_RESTORE_R3 R3 = SAVE_R3;
#else
#define CALLER_SAVE_R3 /* nothing */
#define CALLER_RESTORE_R3 /* nothing */
#endif
#ifdef CALLER_SAVES_R4
#define CALLER_SAVE_R4 SAVE_R4 = R4;
#define CALLER_RESTORE_R4 R4 = SAVE_R4;
#else
#define CALLER_SAVE_R4 /* nothing */
#define CALLER_RESTORE_R4 /* nothing */
#endif
#ifdef CALLER_SAVES_R5
#define CALLER_SAVE_R5 SAVE_R5 = R5;
#define CALLER_RESTORE_R5 R5 = SAVE_R5;
#else
#define CALLER_SAVE_R5 /* nothing */
#define CALLER_RESTORE_R5 /* nothing */
#endif
#ifdef CALLER_SAVES_R6
#define CALLER_SAVE_R6 SAVE_R6 = R6;
#define CALLER_RESTORE_R6 R6 = SAVE_R6;
#else
#define CALLER_SAVE_R6 /* nothing */
#define CALLER_RESTORE_R6 /* nothing */
#endif
#ifdef CALLER_SAVES_R7
#define CALLER_SAVE_R7 SAVE_R7 = R7;
#define CALLER_RESTORE_R7 R7 = SAVE_R7;
#else
#define CALLER_SAVE_R7 /* nothing */
#define CALLER_RESTORE_R7 /* nothing */
#endif
#ifdef CALLER_SAVES_R8
#define CALLER_SAVE_R8 SAVE_R8 = R8;
#define CALLER_RESTORE_R8 R8 = SAVE_R8;
#else
#define CALLER_SAVE_R8 /* nothing */
#define CALLER_RESTORE_R8 /* nothing */
#endif
#ifdef CALLER_SAVES_FltReg1
#define CALLER_SAVE_FltReg1 SAVE_Flt1 = FltReg1;
#define CALLER_RESTORE_FltReg1 FltReg1 = SAVE_Flt1;
#else
#define CALLER_SAVE_FltReg1 /* nothing */
#define CALLER_RESTORE_FltReg1 /* nothing */
#endif
#ifdef CALLER_SAVES_FltReg2
#define CALLER_SAVE_FltReg2 SAVE_Flt2 = FltReg2;
#define CALLER_RESTORE_FltReg2 FltReg2 = SAVE_Flt2;
#else
#define CALLER_SAVE_FltReg2 /* nothing */
#define CALLER_RESTORE_FltReg2 /* nothing */
#endif
#ifdef CALLER_SAVES_FltReg3
#define CALLER_SAVE_FltReg3 SAVE_Flt3 = FltReg3;
#define CALLER_RESTORE_FltReg3 FltReg3 = SAVE_Flt3;
#else
#define CALLER_SAVE_FltReg3 /* nothing */
#define CALLER_RESTORE_FltReg3 /* nothing */
#endif
#ifdef CALLER_SAVES_FltReg4
#define CALLER_SAVE_FltReg4 SAVE_Flt4 = FltReg4;
#define CALLER_RESTORE_FltReg4 FltReg4 = SAVE_Flt4;
#else
#define CALLER_SAVE_FltReg4 /* nothing */
#define CALLER_RESTORE_FltReg4 /* nothing */
#endif
#ifdef CALLER_SAVES_DblReg1
#define CALLER_SAVE_DblReg1 SAVE_Dbl1 = DblReg1;
#define CALLER_RESTORE_DblReg1 DblReg1 = SAVE_Dbl1;
#else
#define CALLER_SAVE_DblReg1 /* nothing */
#define CALLER_RESTORE_DblReg1 /* nothing */
#endif
#ifdef CALLER_SAVES_DblReg2
#define CALLER_SAVE_DblReg2 SAVE_Dbl2 = DblReg2;
#define CALLER_RESTORE_DblReg2 DblReg2 = SAVE_Dbl2;
#else
#define CALLER_SAVE_DblReg2 /* nothing */
#define CALLER_RESTORE_DblReg2 /* nothing */
#endif
#ifdef CALLER_SAVES_Tag
#define CALLER_SAVE_Tag SAVE_Tag = TagReg;
#define CALLER_RESTORE_Tag TagReg = SAVE_Tag;
#else
#define CALLER_SAVE_Tag /* nothing */
#define CALLER_RESTORE_Tag /* nothing */
#endif
#ifdef CALLER_SAVES_Ret
#define CALLER_SAVE_Ret SAVE_Ret = RetReg;
#define CALLER_RESTORE_Ret RetReg = SAVE_Ret;
#else
#define CALLER_SAVE_Ret /* nothing */
#define CALLER_RESTORE_Ret /* nothing */
#endif
#ifdef CALLER_SAVES_SpA
#define CALLER_SAVE_SpA SAVE_SpA = SpA;
#define CALLER_RESTORE_SpA SpA = SAVE_SpA;
#else
#define CALLER_SAVE_SpA /* nothing */
#define CALLER_RESTORE_SpA /* nothing */
#endif
#ifdef CALLER_SAVES_SuA
#define CALLER_SAVE_SuA SAVE_SuA = SuA;
#define CALLER_RESTORE_SuA SuA = SAVE_SuA;
#else
#define CALLER_SAVE_SuA /* nothing */
#define CALLER_RESTORE_SuA /* nothing */
#endif
#ifdef CALLER_SAVES_SpB
#define CALLER_SAVE_SpB SAVE_SpB = SpB;
#define CALLER_RESTORE_SpB SpB = SAVE_SpB;
#else
#define CALLER_SAVE_SpB /* nothing */
#define CALLER_RESTORE_SpB /* nothing */
#endif
#ifdef CALLER_SAVES_SuB
#define CALLER_SAVE_SuB SAVE_SuB = SuB;
#define CALLER_RESTORE_SuB SuB = SAVE_SuB;
#else
#define CALLER_SAVE_SuB /* nothing */
#define CALLER_RESTORE_SuB /* nothing */
#endif
#ifdef CALLER_SAVES_Hp
#define CALLER_SAVE_Hp SAVE_Hp = Hp;
#define CALLER_RESTORE_Hp Hp = SAVE_Hp;
#else
#define CALLER_SAVE_Hp /* nothing */
#define CALLER_RESTORE_Hp /* nothing */
#endif
#ifdef CALLER_SAVES_HpLim
#define CALLER_SAVE_HpLim SAVE_HpLim = HpLim;
#define CALLER_RESTORE_HpLim HpLim = SAVE_HpLim;
#else
#define CALLER_SAVE_HpLim /* nothing */
#define CALLER_RESTORE_HpLim /* nothing */
#endif
#ifdef CALLER_SAVES_Liveness
#define CALLER_SAVE_Liveness SAVE_Liveness = LivenessReg;
#define CALLER_RESTORE_Liveness LivenessReg = SAVE_Liveness;
#else
#define CALLER_SAVE_Liveness /* nothing */
#define CALLER_RESTORE_Liveness /* nothing */
#endif
#ifdef CALLER_SAVES_Base
#ifndef CONCURRENT
#define CALLER_SAVE_Base /* nothing, ever (it holds a fixed value) */
#define CALLER_RESTORE_Base BaseReg = &MainRegTable;
#else
#define CALLER_SAVE_Base /* nothing */
#define CALLER_RESTORE_Base BaseReg = CurrentRegTable;
#endif
#else
#define CALLER_SAVE_Base /* nothing */
#define CALLER_RESTORE_Base /* nothing */
#endif
#ifdef CALLER_SAVES_StdUpdRetVec
#define CALLER_RESTORE_StdUpdRetVec StdUpdRetVecReg = vtbl_StdUpdFrame;
#else
#define CALLER_RESTORE_StdUpdRetVec /* nothing */
#endif
#ifdef CALLER_SAVES_StkStub
#define CALLER_RESTORE_StkStub StdUpdRetVecReg = STK_STUB_closure;
#else
#define CALLER_RESTORE_StkStub /* nothing */
#endif
\end{code}
Concluding \tr{#endifs} and multi-slurp protection:
\begin{code}
#endif /* SCAV_REG_MAP */
#endif /* SCAN_REG_MAP */
#endif /* MARK_REG_MAP */
#endif /* NULL_REG_MAP */
#endif /* STGREGS_H */
\end{code}
|