3 * Generate defines for the needed hardops.
12 #ifdef HAVE_C99_FORMAT
15 #if defined(_WIN64) || defined(LP64)
27 char *cname
= "external.c";
28 char *hname
= "external.h";
32 * masks for matching dope with shapes
36 SIMPFLG
|ASGFLG
, /* ASG OPSIMP */
38 COMMFLG
|ASGFLG
, /* ASG OPCOMM */
40 MULFLG
|ASGFLG
, /* ASG OPMUL */
42 DIVFLG
|ASGFLG
, /* ASG OPDIV */
44 TYFLG
, /* ASG OPUNARY is senseless */
46 TYFLG
, /* ASG OPLEAF is senseless */
48 ASGOPFLG
|ASGFLG
, /* ASG OPANY */
50 TYFLG
, /* ASG OPLOG is senseless */
52 FLOFLG
|ASGFLG
, /* ASG OPFLOAT */
54 SHFFLG
|ASGFLG
, /* ASG OPSHIFT */
56 TYFLG
, /* ASG OPLTYPE is senseless */
64 { MUL
, TLONGLONG
, "SMULLL", },
65 { DIV
, TLONGLONG
, "SDIVLL", },
66 { MOD
, TLONGLONG
, "SMODLL", },
67 { PLUS
, TLONGLONG
, "SPLUSLL", },
68 { MINUS
, TLONGLONG
, "SMINUSLL", },
69 { MUL
, TULONGLONG
, "UMULLL", },
70 { DIV
, TULONGLONG
, "UDIVLL", },
71 { MOD
, TULONGLONG
, "UMODLL", },
72 { PLUS
, TULONGLONG
, "UPLUSLL", },
73 { MINUS
, TULONGLONG
, "UMINUSLL", },
77 int rstatus
[] = { RSTATUS
};
78 int roverlay
[MAXREGS
][MAXREGS
] = { ROVERLAP
};
79 int regclassmap
[CLASSG
][MAXREGS
]; /* CLASSG is highest class */
82 compl(struct optab
*q
, char *str
)
91 default: s
= "Special op"; break;
92 case OPSIMP
: s
= "OPLSIMP"; break;
93 case OPCOMM
: s
= "OPCOMM"; break;
94 case OPMUL
: s
= "OPMUL"; break;
95 case OPDIV
: s
= "OPDIV"; break;
96 case OPUNARY
: s
= "OPUNARY"; break;
97 case OPLEAF
: s
= "OPLEAF"; break;
98 case OPANY
: s
= "OPANY"; break;
99 case OPLOG
: s
= "OPLOG"; break;
100 case OPFLOAT
: s
= "OPFLOAT"; break;
101 case OPSHFT
: s
= "OPSHFT"; break;
102 case OPLTYPE
: s
= "OPLTYPE"; break;
105 printf("table entry " FMTdPTR
", op %s: %s\n", q
- table
, s
, str
);
109 getrcl(struct optab
*q
)
112 (NACOUNT
|NBCOUNT
|NCCOUNT
|NDCOUNT
|NECOUNT
|NFCOUNT
|NGCOUNT
);
113 int r
= q
->rewrite
& RESC1
? 1 : q
->rewrite
& RESC2
? 2 : 3;
116 #define INCK(c) while (v & c##COUNT) { \
117 v -= c##REG, i++; if (i == r) return I##c##REG; }
129 main(int argc
, char *argv
[])
133 int i
, j
, areg
, breg
, creg
, dreg
, mx
, ereg
, freg
, greg
;
135 int bitsz
, rval
, nelem
;
139 printf("Entry %d:\n%s\n", i
, table
[i
].cstring
);
145 for (q
= table
; q
->op
!= FREE
; q
++) {
148 if ((q
->ltype
& TLONGLONG
) &&
149 (q
->rtype
& TLONGLONG
))
150 chkop
[q
->op
] |= TLONGLONG
;
151 if ((q
->ltype
& TULONGLONG
) &&
152 (q
->rtype
& TULONGLONG
))
153 chkop
[q
->op
] |= TULONGLONG
;
155 if ((fc
= fopen(cname
, "w")) == NULL
) {
156 perror("open cfile");
159 if ((fh
= fopen(hname
, "w")) == NULL
) {
160 perror("open hfile");
163 fprintf(fh
, "#ifndef _EXTERNAL_H_\n#define _EXTERNAL_H_\n");
165 for (ch
= checks
; ch
->op
!= 0; ch
++) {
166 if ((chkop
[ch
->op
] & ch
->type
) == 0)
167 fprintf(fh
, "#define NEED_%s\n", ch
->name
);
170 fprintf(fc
, "#include \"pass2.h\"\n");
171 /* create fast-lookup tables */
174 /* create efficient bitset sizes */
175 if (sizeof(long) == 8) { /* 64-bit arch */
180 bitsz
= sizeof(int) == 4 ? 32 : 16;
182 fprintf(fh
, "#define NUMBITS %d\n", bitsz
);
183 fprintf(fh
, "#define BIT2BYTE(bits) "
184 "((((bits)+NUMBITS-1)/NUMBITS)*(NUMBITS/8))\n");
185 fprintf(fh
, "#define BITSET(arr, bit) "
186 "(arr[bit/NUMBITS] |= ((%s)1 << (bit & (NUMBITS-1))))\n",
188 fprintf(fh
, "#define BITCLEAR(arr, bit) "
189 "(arr[bit/NUMBITS] &= ~((%s)1 << (bit & (NUMBITS-1))))\n",
191 fprintf(fh
, "#define TESTBIT(arr, bit) "
192 "(arr[bit/NUMBITS] & ((%s)1 << (bit & (NUMBITS-1))))\n",
194 fprintf(fh
, "typedef %s bittype;\n", bitary
);
196 /* register class definitions, used by graph-coloring */
199 /* Sanity-check the table */
201 for (q
= table
; q
->op
!= FREE
; q
++) {
204 #define F(x) (q->visit & x && q->rewrite & (RLEFT|RRIGHT) && \
205 q->lshape & ~x && q->rshape & ~x)
206 if (F(INAREG
) || F(INBREG
) || F(INCREG
) || F(INDREG
) ||
207 F(INEREG
) || F(INFREG
) || F(INGREG
)) {
208 compl(q
, "may match without result register");
214 if ((q
->visit
& INREGS
) && !(q
->rewrite
& RDEST
)) {
215 compl(q
, "ASSIGN/STASG reclaim must be RDEST");
220 /* check that reclaim is not the wrong class */
221 if ((q
->rewrite
& (RESC1
|RESC2
|RESC3
)) &&
222 !(q
->needs
& REWRITE
)) {
223 if ((q
->visit
& getrcl(q
)) == 0) {
224 compl(q
, "wrong RESCx class");
228 if (q
->rewrite
& (RESC1
|RESC2
|RESC3
) && q
->visit
& FOREFF
)
229 compl(q
, "FOREFF may cause reclaim of wrong class");
232 /* print out list of scratched and permanent registers */
233 fprintf(fh
, "extern int tempregs[], permregs[];\n");
234 fprintf(fc
, "int tempregs[] = { ");
235 for (i
= j
= 0; i
< MAXREGS
; i
++)
236 if (rstatus
[i
] & TEMPREG
)
237 fprintf(fc
, "%d, ", i
), j
++;
238 fprintf(fc
, "-1 };\n");
239 fprintf(fh
, "#define NTEMPREG %d\n", j
+1);
240 fprintf(fh
, "#define FREGS %d\n", j
); /* XXX - to die */
241 fprintf(fc
, "int permregs[] = { ");
242 for (i
= j
= 0; i
< MAXREGS
; i
++)
243 if (rstatus
[i
] & PERMREG
)
244 fprintf(fc
, "%d, ", i
), j
++;
245 fprintf(fc
, "-1 };\n");
246 fprintf(fh
, "#define NPERMREG %d\n", j
+1);
247 fprintf(fc
, "bittype validregs[] = {\n");
250 for (j
= 0; j
< MAXREGS
; j
+= bitsz
) {
252 for (i
= 0; i
< bitsz
; i
++) {
255 if (rstatus
[i
+j
] & INREGS
)
256 cbit
|= ((long)1 << i
);
258 fprintf(fc
, "\t0x%lx,\n", cbit
);
261 for (j
= 0; j
< MAXREGS
; j
+= bitsz
) {
263 for (i
= 0; i
< bitsz
; i
++) {
266 if (rstatus
[i
+j
] & INREGS
)
269 fprintf(fc
, "\t0x%08x,\n", cbit
);
274 fprintf(fh
, "extern bittype validregs[];\n");
277 * The register allocator uses bitmasks of registers for each class.
279 areg
= breg
= creg
= dreg
= ereg
= freg
= greg
= 0;
280 for (i
= 0; i
< MAXREGS
; i
++) {
281 for (j
= 0; j
< NUMCLASS
; j
++)
282 regclassmap
[j
][i
] = -1;
283 if (rstatus
[i
] & SAREG
) regclassmap
[0][i
] = areg
++;
284 if (rstatus
[i
] & SBREG
) regclassmap
[1][i
] = breg
++;
285 if (rstatus
[i
] & SCREG
) regclassmap
[2][i
] = creg
++;
286 if (rstatus
[i
] & SDREG
) regclassmap
[3][i
] = dreg
++;
287 if (rstatus
[i
] & SEREG
) regclassmap
[4][i
] = ereg
++;
288 if (rstatus
[i
] & SFREG
) regclassmap
[5][i
] = freg
++;
289 if (rstatus
[i
] & SGREG
) regclassmap
[6][i
] = greg
++;
291 fprintf(fh
, "#define AREGCNT %d\n", areg
);
292 fprintf(fh
, "#define BREGCNT %d\n", breg
);
293 fprintf(fh
, "#define CREGCNT %d\n", creg
);
294 fprintf(fh
, "#define DREGCNT %d\n", dreg
);
295 fprintf(fh
, "#define EREGCNT %d\n", ereg
);
296 fprintf(fh
, "#define FREGCNT %d\n", freg
);
297 fprintf(fh
, "#define GREGCNT %d\n", greg
);
299 printf("%d regs in class A (max %d)\n", areg
, bitsz
), rval
++;
301 printf("%d regs in class B (max %d)\n", breg
, bitsz
), rval
++;
303 printf("%d regs in class C (max %d)\n", creg
, bitsz
), rval
++;
305 printf("%d regs in class D (max %d)\n", dreg
, bitsz
), rval
++;
307 printf("%d regs in class E (max %d)\n", ereg
, bitsz
), rval
++;
309 printf("%d regs in class F (max %d)\n", freg
, bitsz
), rval
++;
311 printf("%d regs in class G (max %d)\n", greg
, bitsz
), rval
++;
313 fprintf(fc
, "static int amap[MAXREGS][NUMCLASS] = {\n");
314 for (i
= 0; i
< MAXREGS
; i
++) {
315 int ba
, bb
, bc
, bd
, r
, be
, bf
, bg
;
316 ba
= bb
= bc
= bd
= be
= bf
= bg
= 0;
317 if (rstatus
[i
] & SAREG
) ba
= (1 << regclassmap
[0][i
]);
318 if (rstatus
[i
] & SBREG
) bb
= (1 << regclassmap
[1][i
]);
319 if (rstatus
[i
] & SCREG
) bc
= (1 << regclassmap
[2][i
]);
320 if (rstatus
[i
] & SDREG
) bd
= (1 << regclassmap
[3][i
]);
321 if (rstatus
[i
] & SEREG
) be
= (1 << regclassmap
[4][i
]);
322 if (rstatus
[i
] & SFREG
) bf
= (1 << regclassmap
[5][i
]);
323 if (rstatus
[i
] & SGREG
) bg
= (1 << regclassmap
[6][i
]);
324 for (j
= 0; roverlay
[i
][j
] >= 0; j
++) {
326 if (rstatus
[r
] & SAREG
)
327 ba
|= (1 << regclassmap
[0][r
]);
328 if (rstatus
[r
] & SBREG
)
329 bb
|= (1 << regclassmap
[1][r
]);
330 if (rstatus
[r
] & SCREG
)
331 bc
|= (1 << regclassmap
[2][r
]);
332 if (rstatus
[r
] & SDREG
)
333 bd
|= (1 << regclassmap
[3][r
]);
334 if (rstatus
[r
] & SEREG
)
335 be
|= (1 << regclassmap
[4][r
]);
336 if (rstatus
[r
] & SFREG
)
337 bf
|= (1 << regclassmap
[5][r
]);
338 if (rstatus
[r
] & SGREG
)
339 bg
|= (1 << regclassmap
[6][r
]);
341 fprintf(fc
, "\t/* %d */{ 0x%x", i
, ba
);
342 if (NUMCLASS
> 1) fprintf(fc
, ",0x%x", bb
);
343 if (NUMCLASS
> 2) fprintf(fc
, ",0x%x", bc
);
344 if (NUMCLASS
> 3) fprintf(fc
, ",0x%x", bd
);
345 if (NUMCLASS
> 4) fprintf(fc
, ",0x%x", be
);
346 if (NUMCLASS
> 5) fprintf(fc
, ",0x%x", bf
);
347 if (NUMCLASS
> 6) fprintf(fc
, ",0x%x", bg
);
348 fprintf(fc
, " },\n");
352 fprintf(fh
, "int aliasmap(int class, int regnum);\n");
353 fprintf(fc
, "int\naliasmap(int class, int regnum)\n{\n");
354 fprintf(fc
, " return amap[regnum][class-1];\n}\n");
356 /* routines to convert back from color to regnum */
358 if (breg
> mx
) mx
= breg
;
359 if (creg
> mx
) mx
= creg
;
360 if (dreg
> mx
) mx
= dreg
;
361 if (ereg
> mx
) mx
= ereg
;
362 if (freg
> mx
) mx
= freg
;
363 if (greg
> mx
) mx
= greg
;
364 if (mx
> (int)(sizeof(int)*8)-1) {
365 printf("too many regs in a class, use two classes instead\n");
366 #ifdef HAVE_C99_FORMAT
367 printf("%d > %zu\n", mx
, (sizeof(int)*8)-1);
369 printf("%d > %d\n", mx
, (int)(sizeof(int)*8)-1);
373 fprintf(fc
, "static int rmap[NUMCLASS][%d] = {\n", mx
);
374 for (j
= 0; j
< NUMCLASS
; j
++) {
375 int cl
= (1 << (j
+1));
377 for (i
= 0; i
< MAXREGS
; i
++)
378 if (rstatus
[i
] & cl
) fprintf(fc
, "%d, ", i
);
381 fprintf(fc
, "};\n\n");
383 fprintf(fh
, "int color2reg(int color, int class);\n");
384 fprintf(fc
, "int\ncolor2reg(int color, int class)\n{\n");
385 fprintf(fc
, " return rmap[class-1][color];\n}\n");
387 /* used by register allocator */
388 fprintf(fc
, "int regK[] = { 0, %d, %d, %d, %d, %d, %d, %d };\n",
389 areg
, breg
, creg
, dreg
, ereg
, freg
, greg
);
390 fprintf(fc
, "int\nclassmask(int class)\n{\n");
391 fprintf(fc
, "\tif(class == CLASSA) return 0x%x;\n", (1 << areg
)-1);
392 fprintf(fc
, "\tif(class == CLASSB) return 0x%x;\n", (1 << breg
)-1);
393 fprintf(fc
, "\tif(class == CLASSC) return 0x%x;\n", (1 << creg
)-1);
394 fprintf(fc
, "\tif(class == CLASSD) return 0x%x;\n", (1 << dreg
)-1);
395 fprintf(fc
, "\tif(class == CLASSE) return 0x%x;\n", (1 << ereg
)-1);
396 fprintf(fc
, "\tif(class == CLASSF) return 0x%x;\n", (1 << freg
)-1);
397 fprintf(fc
, "\treturn 0x%x;\n}\n", (1 << greg
)-1);
399 fprintf(fh
, "int interferes(int reg1, int reg2);\n");
400 nelem
= (MAXREGS
+bitsz
-1)/bitsz
;
401 fprintf(fc
, "static bittype ovlarr[MAXREGS][%d] = {\n", nelem
);
402 for (i
= 0; i
< MAXREGS
; i
++) {
404 memset(el
, 0, sizeof(el
));
405 el
[i
/bitsz
] = 1 << (i
% bitsz
);
406 for (j
= 0; roverlay
[i
][j
] >= 0; j
++) {
407 int k
= roverlay
[i
][j
];
408 el
[k
/bitsz
] |= (1 << (k
% bitsz
));
411 for (j
= 0; j
< MAXREGS
; j
+= bitsz
)
412 fprintf(fc
, "0x%x, ", el
[j
/bitsz
]);
413 fprintf(fc
, " },\n");
417 fprintf(fc
, "int\ninterferes(int reg1, int reg2)\n{\n");
418 fprintf(fc
, "return (TESTBIT(ovlarr[reg1], reg2)) != 0;\n}\n");
420 fprintf(fh
, "#endif /* _EXTERNAL_H_ */\n");
425 #define P(x) fprintf x
431 int mxalen
= 0, curalen
;
435 P((fc
, "#include \"pass2.h\"\n\n"));
437 for (i
= 0; i
<= MAXOP
; i
++) {
439 P((fc
, "static int op%d[] = { ", i
));
441 for (op
= table
; op
->op
!= FREE
; op
++) {
442 if (op
->op
< OPSIMP
) {
444 P((fc
, FMTdPTR
", ", op
- table
));
449 if ((opmtemp
=mamask
[op
->op
- OPSIMP
])&SPFLG
) {
450 if (i
==NAME
|| i
==ICON
|| i
==TEMP
||
451 i
==OREG
|| i
== REG
|| i
== FCON
) {
456 } else if ((dope
[i
]&(opmtemp
|ASGFLG
))==opmtemp
){
457 P((fc
, FMTdPTR
", ", op
- table
));
462 if (curalen
> mxalen
)
468 P((fc
, "int *qtable[] = { \n"));
469 for (i
= 0; i
<= MAXOP
; i
++) {
470 P((fc
, " op%d,\n", i
));
473 P((fh
, "#define MAXOPLEN %d\n", mxalen
+1));