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