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