xref: /netbsd-src/external/bsd/pcc/dist/pcc/mip/mkext.c (revision 3862d4bab153103b9c3d09043872889458100388)
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