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