* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / mip / mkext.c
blob0fabe42f2a96d0616ba7b2098df9343e61881945
2 /*
3 * Generate defines for the needed hardops.
4 */
5 #include "pass2.h"
6 #include <stdlib.h>
8 #ifdef HAVE_STRING_H
9 #include <string.h>
10 #endif
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
22 int chkop[DSIZE];
24 void mktables(void);
26 char *ftitle;
27 char *cname = "external.c";
28 char *hname = "external.h";
29 FILE *fc, *fh;
32 * masks for matching dope with shapes
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 */
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, },
77 int rstatus[] = { RSTATUS };
78 int roverlay[MAXREGS][MAXREGS] = { ROVERLAP };
79 int regclassmap[CLASSG][MAXREGS]; /* CLASSG is highest class */
81 static void
82 compl(struct optab *q, char *str)
84 int op = q->op;
85 char *s;
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;
105 printf("table entry " FMTdPTR ", op %s: %s\n", q - table, s, str);
108 static int
109 getrcl(struct optab *q)
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;
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;
129 main(int argc, char *argv[])
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;
137 if (argc == 2) {
138 i = atoi(argv[1]);
139 printf("Entry %d:\n%s\n", i, table[i].cstring);
140 return 0;
143 mkdope();
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;
155 if ((fc = fopen(cname, "w")) == NULL) {
156 perror("open cfile");
157 return(1);
159 if ((fh = fopen(hname, "w")) == NULL) {
160 perror("open hfile");
161 return(1);
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 */
172 mktables();
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;
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);
196 /* register class definitions, used by graph-coloring */
197 /* TODO */
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++;
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++;
218 break;
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++;
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");
249 if (bitsz == 64) {
250 for (j = 0; j < MAXREGS; j += bitsz) {
251 long cbit = 0;
252 for (i = 0; i < bitsz; i++) {
253 if (i+j == MAXREGS)
254 break;
255 if (rstatus[i+j] & INREGS)
256 cbit |= ((long)1 << i);
258 fprintf(fc, "\t0x%lx,\n", cbit);
260 } else {
261 for (j = 0; j < MAXREGS; j += bitsz) {
262 int cbit = 0;
263 for (i = 0; i < bitsz; i++) {
264 if (i+j == MAXREGS)
265 break;
266 if (rstatus[i+j] & INREGS)
267 cbit |= (1 << i);
269 fprintf(fc, "\t0x%08x,\n", cbit);
273 fprintf(fc, "};\n");
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);
298 if (areg > bitsz)
299 printf("%d regs in class A (max %d)\n", areg, bitsz), rval++;
300 if (breg > bitsz)
301 printf("%d regs in class B (max %d)\n", breg, bitsz), rval++;
302 if (creg > bitsz)
303 printf("%d regs in class C (max %d)\n", creg, bitsz), rval++;
304 if (dreg > bitsz)
305 printf("%d regs in class D (max %d)\n", dreg, bitsz), rval++;
306 if (ereg > bitsz)
307 printf("%d regs in class E (max %d)\n", ereg, bitsz), rval++;
308 if (freg > bitsz)
309 printf("%d regs in class F (max %d)\n", freg, bitsz), rval++;
310 if (greg > bitsz)
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++) {
325 r = roverlay[i][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");
350 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 */
357 mx = areg;
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);
368 #else
369 printf("%d > %d\n", mx, (int)(sizeof(int)*8)-1);
370 #endif
371 rval++;
373 fprintf(fc, "static int rmap[NUMCLASS][%d] = {\n", mx);
374 for (j = 0; j < NUMCLASS; j++) {
375 int cl = (1 << (j+1));
376 fprintf(fc, "\t{ ");
377 for (i = 0; i < MAXREGS; i++)
378 if (rstatus[i] & cl) fprintf(fc, "%d, ", i);
379 fprintf(fc, "},\n");
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++) {
403 int el[10];
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));
410 fprintf(fc, "{ ");
411 for (j = 0; j < MAXREGS; j += bitsz)
412 fprintf(fc, "0x%x, ", el[j/bitsz]);
413 fprintf(fc, " },\n");
415 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");
419 fclose(fc);
420 fprintf(fh, "#endif /* _EXTERNAL_H_ */\n");
421 fclose(fh);
422 return rval;
425 #define P(x) fprintf x
427 void
428 mktables()
430 struct optab *op;
431 int mxalen = 0, curalen;
432 int i;
434 #if 0
435 P((fc, "#include \"pass2.h\"\n\n"));
436 #endif
437 for (i = 0; i <= MAXOP; i++) {
438 curalen = 0;
439 P((fc, "static int op%d[] = { ", i));
440 if (dope[i] != 0)
441 for (op = table; op->op != FREE; op++) {
442 if (op->op < OPSIMP) {
443 if (op->op == i) {
444 P((fc, FMTdPTR ", ", op - table));
445 curalen++;
447 } else {
448 int opmtemp;
449 if ((opmtemp=mamask[op->op - OPSIMP])&SPFLG) {
450 if (i==NAME || i==ICON || i==TEMP ||
451 i==OREG || i == REG || i == FCON) {
452 P((fc, FMTdPTR ", ",
453 op - table));
454 curalen++;
456 } else if ((dope[i]&(opmtemp|ASGFLG))==opmtemp){
457 P((fc, FMTdPTR ", ", op - table));
458 curalen++;
462 if (curalen > mxalen)
463 mxalen = curalen;
464 P((fc, "-1 };\n"));
466 P((fc, "\n"));
468 P((fc, "int *qtable[] = { \n"));
469 for (i = 0; i <= MAXOP; i++) {
470 P((fc, " op%d,\n", i));
472 P((fc, "};\n"));
473 P((fh, "#define MAXOPLEN %d\n", mxalen+1));