1 /* Id: mkext.c,v 1.52 2014/03/11 21:32:18 ragge Exp */
2 /* $NetBSD: mkext.c,v 1.1.1.5 2014/07/24 19:28:50 plunky Exp $ */
3
4 /*
5 * Generate defines for the needed hardops.
6 */
7 #include "pass2.h"
8 #include <stdlib.h>
9
10 #ifdef HAVE_STRING_H
11 #include <string.h>
12 #endif
13
14 #ifdef HAVE_C99_FORMAT
15 #define FMTdPTR "%td"
16 #else
17 #if defined(_WIN64) || defined(LP64)
18 #define FMTdPTR "%ld"
19 #else
20 #define FMTdPTR "%d"
21 #endif
22 #endif
23
24 int chkop[DSIZE];
25
26 void mktables(void);
27
28 char *ftitle;
29 char *cname = "external.c";
30 char *hname = "external.h";
31 FILE *fc, *fh;
32
33 /*
34 * masks for matching dope with shapes
35 */
36 int mamask[] = {
37 SIMPFLG, /* OPSIMP */
38 SIMPFLG|ASGFLG, /* ASG OPSIMP */
39 COMMFLG, /* OPCOMM */
40 COMMFLG|ASGFLG, /* ASG OPCOMM */
41 MULFLG, /* OPMUL */
42 MULFLG|ASGFLG, /* ASG OPMUL */
43 DIVFLG, /* OPDIV */
44 DIVFLG|ASGFLG, /* ASG OPDIV */
45 UTYPE, /* OPUNARY */
46 TYFLG, /* ASG OPUNARY is senseless */
47 LTYPE, /* OPLEAF */
48 TYFLG, /* ASG OPLEAF is senseless */
49 0, /* OPANY */
50 ASGOPFLG|ASGFLG, /* ASG OPANY */
51 LOGFLG, /* OPLOG */
52 TYFLG, /* ASG OPLOG is senseless */
53 FLOFLG, /* OPFLOAT */
54 FLOFLG|ASGFLG, /* ASG OPFLOAT */
55 SHFFLG, /* OPSHFT */
56 SHFFLG|ASGFLG, /* ASG OPSHIFT */
57 SPFLG, /* OPLTYPE */
58 TYFLG, /* ASG OPLTYPE is senseless */
59 };
60
61
62 struct checks {
63 int op, type;
64 char *name;
65 } checks[] = {
66 { MUL, TLONGLONG, "SMULLL", },
67 { DIV, TLONGLONG, "SDIVLL", },
68 { MOD, TLONGLONG, "SMODLL", },
69 { PLUS, TLONGLONG, "SPLUSLL", },
70 { MINUS, TLONGLONG, "SMINUSLL", },
71 { MUL, TULONGLONG, "UMULLL", },
72 { DIV, TULONGLONG, "UDIVLL", },
73 { MOD, TULONGLONG, "UMODLL", },
74 { PLUS, TULONGLONG, "UPLUSLL", },
75 { MINUS, TULONGLONG, "UMINUSLL", },
76 { 0, 0, 0, },
77 };
78
79 int rstatus[] = { RSTATUS };
80 int roverlay[MAXREGS][MAXREGS] = { ROVERLAP };
81 int regclassmap[CLASSG][MAXREGS]; /* CLASSG is highest class */
82
83 static void
compl(struct optab * q,char * str)84 compl(struct optab *q, char *str)
85 {
86 int op = q->op;
87 char *s;
88
89 if (op < OPSIMP) {
90 s = opst[op];
91 } else
92 switch (op) {
93 default: s = "Special op"; break;
94 case OPSIMP: s = "OPLSIMP"; break;
95 case OPCOMM: s = "OPCOMM"; break;
96 case OPMUL: s = "OPMUL"; break;
97 case OPDIV: s = "OPDIV"; break;
98 case OPUNARY: s = "OPUNARY"; break;
99 case OPLEAF: s = "OPLEAF"; break;
100 case OPANY: s = "OPANY"; break;
101 case OPLOG: s = "OPLOG"; break;
102 case OPFLOAT: s = "OPFLOAT"; break;
103 case OPSHFT: s = "OPSHFT"; break;
104 case OPLTYPE: s = "OPLTYPE"; break;
105 }
106
107 printf("table entry " FMTdPTR ", op %s: %s\n", q - table, s, str);
108 }
109
110 static int
getrcl(struct optab * q)111 getrcl(struct optab *q)
112 {
113 int v = q->needs &
114 (NACOUNT|NBCOUNT|NCCOUNT|NDCOUNT|NECOUNT|NFCOUNT|NGCOUNT);
115 int r = q->rewrite & RESC1 ? 1 : q->rewrite & RESC2 ? 2 : 3;
116 int i = 0;
117
118 #define INCK(c) while (v & c##COUNT) { \
119 v -= c##REG, i++; if (i == r) return I##c##REG; }
120 INCK(NA)
121 INCK(NB)
122 INCK(NC)
123 INCK(ND)
124 INCK(NE)
125 INCK(NF)
126 INCK(NG)
127 return 0;
128 }
129
130 int
main(int argc,char * argv[])131 main(int argc, char *argv[])
132 {
133 struct optab *q;
134 struct checks *ch;
135 int i, j, areg, breg, creg, dreg, mx, ereg, freg, greg;
136 char *bitary;
137 int bitsz, rval, nelem;
138
139 if (argc == 2) {
140 i = atoi(argv[1]);
141 printf("Entry %d:\n%s\n", i, table[i].cstring);
142 return 0;
143 }
144
145 mkdope();
146
147 for (q = table; q->op != FREE; q++) {
148 if (q->op >= OPSIMP)
149 continue;
150 if ((q->ltype & TLONGLONG) &&
151 (q->rtype & TLONGLONG))
152 chkop[q->op] |= TLONGLONG;
153 if ((q->ltype & TULONGLONG) &&
154 (q->rtype & TULONGLONG))
155 chkop[q->op] |= TULONGLONG;
156 }
157 if ((fc = fopen(cname, "w")) == NULL) {
158 perror("open cfile");
159 return(1);
160 }
161 if ((fh = fopen(hname, "w")) == NULL) {
162 perror("open hfile");
163 return(1);
164 }
165 fprintf(fh, "#ifndef _EXTERNAL_H_\n#define _EXTERNAL_H_\n");
166
167 for (ch = checks; ch->op != 0; ch++) {
168 if ((chkop[ch->op] & ch->type) == 0)
169 fprintf(fh, "#define NEED_%s\n", ch->name);
170 }
171
172 fprintf(fc, "#include \"pass2.h\"\n");
173 /* create fast-lookup tables */
174 mktables();
175
176 /* create efficient bitset sizes */
177 if (sizeof(long) == 8) { /* 64-bit arch */
178 bitary = "long";
179 bitsz = 64;
180 } else {
181 bitary = "int";
182 bitsz = sizeof(int) == 4 ? 32 : 16;
183 }
184 fprintf(fh, "#define NUMBITS %d\n", bitsz);
185 fprintf(fh, "#define BIT2BYTE(bits) "
186 "((((bits)+NUMBITS-1)/NUMBITS)*(NUMBITS/8))\n");
187 fprintf(fh, "#define BITSET(arr, bit) "
188 "(arr[bit/NUMBITS] |= ((%s)1 << (bit & (NUMBITS-1))))\n",
189 bitary);
190 fprintf(fh, "#define BITCLEAR(arr, bit) "
191 "(arr[bit/NUMBITS] &= ~((%s)1 << (bit & (NUMBITS-1))))\n",
192 bitary);
193 fprintf(fh, "#define TESTBIT(arr, bit) "
194 "(arr[bit/NUMBITS] & ((%s)1 << (bit & (NUMBITS-1))))\n",
195 bitary);
196 fprintf(fh, "typedef %s bittype;\n", bitary);
197
198 /* register class definitions, used by graph-coloring */
199 /* TODO */
200
201 /* Sanity-check the table */
202 rval = 0;
203 for (q = table; q->op != FREE; q++) {
204 switch (q->op) {
205 case ASSIGN:
206 #define F(x) (q->visit & x && q->rewrite & (RLEFT|RRIGHT) && \
207 q->lshape & ~x && q->rshape & ~x)
208 if (F(INAREG) || F(INBREG) || F(INCREG) || F(INDREG) ||
209 F(INEREG) || F(INFREG) || F(INGREG)) {
210 compl(q, "may match without result register");
211 rval++;
212 }
213 #undef F
214 /* FALLTHROUGH */
215 case STASG:
216 if ((q->visit & INREGS) && !(q->rewrite & RDEST)) {
217 compl(q, "ASSIGN/STASG reclaim must be RDEST");
218 rval++;
219 }
220 break;
221 }
222 /* check that reclaim is not the wrong class */
223 if ((q->rewrite & (RESC1|RESC2|RESC3)) &&
224 !(q->needs & REWRITE)) {
225 if ((q->visit & getrcl(q)) == 0) {
226 compl(q, "wrong RESCx class");
227 rval++;
228 }
229 }
230 if (q->rewrite & (RESC1|RESC2|RESC3) && q->visit & FOREFF)
231 compl(q, "FOREFF may cause reclaim of wrong class");
232 }
233
234 /* print out list of scratched and permanent registers */
235 fprintf(fh, "extern int tempregs[], permregs[];\n");
236 fprintf(fc, "int tempregs[] = { ");
237 for (i = j = 0; i < MAXREGS; i++)
238 if (rstatus[i] & TEMPREG)
239 fprintf(fc, "%d, ", i), j++;
240 fprintf(fc, "-1 };\n");
241 fprintf(fh, "#define NTEMPREG %d\n", j+1);
242 fprintf(fh, "#define FREGS %d\n", j); /* XXX - to die */
243 fprintf(fc, "int permregs[] = { ");
244 for (i = j = 0; i < MAXREGS; i++)
245 if (rstatus[i] & PERMREG)
246 fprintf(fc, "%d, ", i), j++;
247 fprintf(fc, "-1 };\n");
248 fprintf(fh, "#define NPERMREG %d\n", j+1);
249 fprintf(fc, "bittype validregs[] = {\n");
250
251 if (bitsz == 64) {
252 for (j = 0; j < MAXREGS; j += bitsz) {
253 long cbit = 0;
254 for (i = 0; i < bitsz; i++) {
255 if (i+j == MAXREGS)
256 break;
257 if (rstatus[i+j] & INREGS)
258 cbit |= ((long)1 << i);
259 }
260 fprintf(fc, "\t0x%lx,\n", cbit);
261 }
262 } else {
263 for (j = 0; j < MAXREGS; j += bitsz) {
264 int cbit = 0;
265 for (i = 0; i < bitsz; i++) {
266 if (i+j == MAXREGS)
267 break;
268 if (rstatus[i+j] & INREGS)
269 cbit |= (1 << i);
270 }
271 fprintf(fc, "\t0x%08x,\n", cbit);
272 }
273 }
274
275 fprintf(fc, "};\n");
276 fprintf(fh, "extern bittype validregs[];\n");
277
278 /*
279 * The register allocator uses bitmasks of registers for each class.
280 */
281 areg = breg = creg = dreg = ereg = freg = greg = 0;
282 for (i = 0; i < MAXREGS; i++) {
283 for (j = 0; j < NUMCLASS; j++)
284 regclassmap[j][i] = -1;
285 if (rstatus[i] & SAREG) regclassmap[0][i] = areg++;
286 if (rstatus[i] & SBREG) regclassmap[1][i] = breg++;
287 if (rstatus[i] & SCREG) regclassmap[2][i] = creg++;
288 if (rstatus[i] & SDREG) regclassmap[3][i] = dreg++;
289 if (rstatus[i] & SEREG) regclassmap[4][i] = ereg++;
290 if (rstatus[i] & SFREG) regclassmap[5][i] = freg++;
291 if (rstatus[i] & SGREG) regclassmap[6][i] = greg++;
292 }
293 fprintf(fh, "#define AREGCNT %d\n", areg);
294 fprintf(fh, "#define BREGCNT %d\n", breg);
295 fprintf(fh, "#define CREGCNT %d\n", creg);
296 fprintf(fh, "#define DREGCNT %d\n", dreg);
297 fprintf(fh, "#define EREGCNT %d\n", ereg);
298 fprintf(fh, "#define FREGCNT %d\n", freg);
299 fprintf(fh, "#define GREGCNT %d\n", greg);
300 if (areg > bitsz)
301 printf("%d regs in class A (max %d)\n", areg, bitsz), rval++;
302 if (breg > bitsz)
303 printf("%d regs in class B (max %d)\n", breg, bitsz), rval++;
304 if (creg > bitsz)
305 printf("%d regs in class C (max %d)\n", creg, bitsz), rval++;
306 if (dreg > bitsz)
307 printf("%d regs in class D (max %d)\n", dreg, bitsz), rval++;
308 if (ereg > bitsz)
309 printf("%d regs in class E (max %d)\n", ereg, bitsz), rval++;
310 if (freg > bitsz)
311 printf("%d regs in class F (max %d)\n", freg, bitsz), rval++;
312 if (greg > bitsz)
313 printf("%d regs in class G (max %d)\n", greg, bitsz), rval++;
314
315 fprintf(fc, "static int amap[MAXREGS][NUMCLASS] = {\n");
316 for (i = 0; i < MAXREGS; i++) {
317 int ba, bb, bc, bd, r, be, bf, bg;
318 ba = bb = bc = bd = be = bf = bg = 0;
319 if (rstatus[i] & SAREG) ba = (1 << regclassmap[0][i]);
320 if (rstatus[i] & SBREG) bb = (1 << regclassmap[1][i]);
321 if (rstatus[i] & SCREG) bc = (1 << regclassmap[2][i]);
322 if (rstatus[i] & SDREG) bd = (1 << regclassmap[3][i]);
323 if (rstatus[i] & SEREG) be = (1 << regclassmap[4][i]);
324 if (rstatus[i] & SFREG) bf = (1 << regclassmap[5][i]);
325 if (rstatus[i] & SGREG) bg = (1 << regclassmap[6][i]);
326 for (j = 0; roverlay[i][j] >= 0; j++) {
327 r = roverlay[i][j];
328 if (rstatus[r] & SAREG)
329 ba |= (1 << regclassmap[0][r]);
330 if (rstatus[r] & SBREG)
331 bb |= (1 << regclassmap[1][r]);
332 if (rstatus[r] & SCREG)
333 bc |= (1 << regclassmap[2][r]);
334 if (rstatus[r] & SDREG)
335 bd |= (1 << regclassmap[3][r]);
336 if (rstatus[r] & SEREG)
337 be |= (1 << regclassmap[4][r]);
338 if (rstatus[r] & SFREG)
339 bf |= (1 << regclassmap[5][r]);
340 if (rstatus[r] & SGREG)
341 bg |= (1 << regclassmap[6][r]);
342 }
343 fprintf(fc, "\t/* %d */{ 0x%x", i, ba);
344 if (NUMCLASS > 1) fprintf(fc, ",0x%x", bb);
345 if (NUMCLASS > 2) fprintf(fc, ",0x%x", bc);
346 if (NUMCLASS > 3) fprintf(fc, ",0x%x", bd);
347 if (NUMCLASS > 4) fprintf(fc, ",0x%x", be);
348 if (NUMCLASS > 5) fprintf(fc, ",0x%x", bf);
349 if (NUMCLASS > 6) fprintf(fc, ",0x%x", bg);
350 fprintf(fc, " },\n");
351 }
352 fprintf(fc, "};\n");
353
354 fprintf(fh, "int aliasmap(int class, int regnum);\n");
355 fprintf(fc, "int\naliasmap(int class, int regnum)\n{\n");
356 fprintf(fc, " return amap[regnum][class-1];\n}\n");
357
358 /* routines to convert back from color to regnum */
359 mx = areg;
360 if (breg > mx) mx = breg;
361 if (creg > mx) mx = creg;
362 if (dreg > mx) mx = dreg;
363 if (ereg > mx) mx = ereg;
364 if (freg > mx) mx = freg;
365 if (greg > mx) mx = greg;
366 if (mx > (int)(sizeof(int)*8)-1) {
367 printf("too many regs in a class, use two classes instead\n");
368 #ifdef HAVE_C99_FORMAT
369 printf("%d > %zu\n", mx, (sizeof(int)*8)-1);
370 #else
371 printf("%d > %d\n", mx, (int)(sizeof(int)*8)-1);
372 #endif
373 rval++;
374 }
375 fprintf(fc, "static int rmap[NUMCLASS][%d] = {\n", mx);
376 for (j = 0; j < NUMCLASS; j++) {
377 int cl = SAREG << j;
378 if (j > 3)
379 cl = SEREG << (j - 4);
380 fprintf(fc, "\t{ ");
381 for (i = 0; i < MAXREGS; i++)
382 if (rstatus[i] & cl) fprintf(fc, "%d, ", i);
383 fprintf(fc, "},\n");
384 }
385 fprintf(fc, "};\n\n");
386
387 fprintf(fh, "int color2reg(int color, int class);\n");
388 fprintf(fc, "int\ncolor2reg(int color, int class)\n{\n");
389 fprintf(fc, " return rmap[class-1][color];\n}\n");
390
391 /* used by register allocator */
392 fprintf(fc, "int regK[] = { 0, %d, %d, %d, %d, %d, %d, %d };\n",
393 areg, breg, creg, dreg, ereg, freg, greg);
394 fprintf(fc, "int\nclassmask(int class)\n{\n");
395 fprintf(fc, "\tif(class == CLASSA) return 0x%x;\n", (1 << areg)-1);
396 fprintf(fc, "\tif(class == CLASSB) return 0x%x;\n", (1 << breg)-1);
397 fprintf(fc, "\tif(class == CLASSC) return 0x%x;\n", (1 << creg)-1);
398 fprintf(fc, "\tif(class == CLASSD) return 0x%x;\n", (1 << dreg)-1);
399 fprintf(fc, "\tif(class == CLASSE) return 0x%x;\n", (1 << ereg)-1);
400 fprintf(fc, "\tif(class == CLASSF) return 0x%x;\n", (1 << freg)-1);
401 fprintf(fc, "\treturn 0x%x;\n}\n", (1 << greg)-1);
402
403 fprintf(fh, "int interferes(int reg1, int reg2);\n");
404 nelem = (MAXREGS+bitsz-1)/bitsz;
405 fprintf(fc, "static bittype ovlarr[MAXREGS][%d] = {\n", nelem);
406 for (i = 0; i < MAXREGS; i++) {
407 int el[10];
408 memset(el, 0, sizeof(el));
409 el[i/bitsz] = 1 << (i % bitsz);
410 for (j = 0; roverlay[i][j] >= 0; j++) {
411 int k = roverlay[i][j];
412 el[k/bitsz] |= (1 << (k % bitsz));
413 }
414 fprintf(fc, "{ ");
415 for (j = 0; j < MAXREGS; j += bitsz)
416 fprintf(fc, "0x%x, ", el[j/bitsz]);
417 fprintf(fc, " },\n");
418 }
419 fprintf(fc, "};\n");
420
421 fprintf(fc, "int\ninterferes(int reg1, int reg2)\n{\n");
422 fprintf(fc, "return (TESTBIT(ovlarr[reg1], reg2)) != 0;\n}\n");
423 fclose(fc);
424 fprintf(fh, "#endif /* _EXTERNAL_H_ */\n");
425 fclose(fh);
426 return rval;
427 }
428
429 #define P(x) fprintf x
430
431 void
mktables(void)432 mktables(void)
433 {
434 struct optab *op;
435 int mxalen = 0, curalen;
436 int i;
437
438 #if 0
439 P((fc, "#include \"pass2.h\"\n\n"));
440 #endif
441 for (i = 0; i <= MAXOP; i++) {
442 curalen = 0;
443 P((fc, "static int op%d[] = { ", i));
444 if (dope[i] != 0)
445 for (op = table; op->op != FREE; op++) {
446 if (op->op < OPSIMP) {
447 if (op->op == i) {
448 P((fc, FMTdPTR ", ", op - table));
449 curalen++;
450 }
451 } else {
452 int opmtemp;
453 if ((opmtemp=mamask[op->op - OPSIMP])&SPFLG) {
454 if (i==NAME || i==ICON || i==TEMP ||
455 i==OREG || i == REG || i == FCON) {
456 P((fc, FMTdPTR ", ",
457 op - table));
458 curalen++;
459 }
460 } else if ((dope[i]&(opmtemp|ASGFLG))==opmtemp){
461 P((fc, FMTdPTR ", ", op - table));
462 curalen++;
463 }
464 }
465 }
466 if (curalen > mxalen)
467 mxalen = curalen;
468 P((fc, "-1 };\n"));
469 }
470 P((fc, "\n"));
471
472 P((fc, "int *qtable[] = { \n"));
473 for (i = 0; i <= MAXOP; i++) {
474 P((fc, " op%d,\n", i));
475 }
476 P((fc, "};\n"));
477 P((fh, "#define MAXOPLEN %d\n", mxalen+1));
478 }
479