1/* Id: mkext.c,v 1.50 2011/06/05 08:54:43 plunky Exp */ 2/* $NetBSD: mkext.c,v 1.1.1.4 2011/09/01 12:47:13 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 24int chkop[DSIZE]; 25 26void mktables(void); 27 28char *ftitle; 29char *cname = "external.c"; 30char *hname = "external.h"; 31FILE *fc, *fh; 32 33/* 34 * masks for matching dope with shapes 35 */ 36int 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 62struct 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 79int rstatus[] = { RSTATUS }; 80int roverlay[MAXREGS][MAXREGS] = { ROVERLAP }; 81int regclassmap[CLASSG][MAXREGS]; /* CLASSG is highest class */ 82 83static void 84compl(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 110static int 111getrcl(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 130int 131main(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 251if (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 = (1 << (j+1)); 378 fprintf(fc, "\t{ "); 379 for (i = 0; i < MAXREGS; i++) 380 if (rstatus[i] & cl) fprintf(fc, "%d, ", i); 381 fprintf(fc, "},\n"); 382 } 383 fprintf(fc, "};\n\n"); 384 385 fprintf(fh, "int color2reg(int color, int class);\n"); 386 fprintf(fc, "int\ncolor2reg(int color, int class)\n{\n"); 387 fprintf(fc, " return rmap[class-1][color];\n}\n"); 388 389 /* used by register allocator */ 390 fprintf(fc, "int regK[] = { 0, %d, %d, %d, %d, %d, %d, %d };\n", 391 areg, breg, creg, dreg, ereg, freg, greg); 392 fprintf(fc, "int\nclassmask(int class)\n{\n"); 393 fprintf(fc, "\tif(class == CLASSA) return 0x%x;\n", (1 << areg)-1); 394 fprintf(fc, "\tif(class == CLASSB) return 0x%x;\n", (1 << breg)-1); 395 fprintf(fc, "\tif(class == CLASSC) return 0x%x;\n", (1 << creg)-1); 396 fprintf(fc, "\tif(class == CLASSD) return 0x%x;\n", (1 << dreg)-1); 397 fprintf(fc, "\tif(class == CLASSE) return 0x%x;\n", (1 << ereg)-1); 398 fprintf(fc, "\tif(class == CLASSF) return 0x%x;\n", (1 << freg)-1); 399 fprintf(fc, "\treturn 0x%x;\n}\n", (1 << greg)-1); 400 401 fprintf(fh, "int interferes(int reg1, int reg2);\n"); 402 nelem = (MAXREGS+bitsz-1)/bitsz; 403 fprintf(fc, "static bittype ovlarr[MAXREGS][%d] = {\n", nelem); 404 for (i = 0; i < MAXREGS; i++) { 405 int el[10]; 406 memset(el, 0, sizeof(el)); 407 el[i/bitsz] = 1 << (i % bitsz); 408 for (j = 0; roverlay[i][j] >= 0; j++) { 409 int k = roverlay[i][j]; 410 el[k/bitsz] |= (1 << (k % bitsz)); 411 } 412 fprintf(fc, "{ "); 413 for (j = 0; j < MAXREGS; j += bitsz) 414 fprintf(fc, "0x%x, ", el[j/bitsz]); 415 fprintf(fc, " },\n"); 416 } 417 fprintf(fc, "};\n"); 418 419 fprintf(fc, "int\ninterferes(int reg1, int reg2)\n{\n"); 420 fprintf(fc, "return (TESTBIT(ovlarr[reg1], reg2)) != 0;\n}\n"); 421 fclose(fc); 422 fprintf(fh, "#endif /* _EXTERNAL_H_ */\n"); 423 fclose(fh); 424 return rval; 425} 426 427#define P(x) fprintf x 428 429void 430mktables() 431{ 432 struct optab *op; 433 int mxalen = 0, curalen; 434 int i; 435 436#if 0 437 P((fc, "#include \"pass2.h\"\n\n")); 438#endif 439 for (i = 0; i <= MAXOP; i++) { 440 curalen = 0; 441 P((fc, "static int op%d[] = { ", i)); 442 if (dope[i] != 0) 443 for (op = table; op->op != FREE; op++) { 444 if (op->op < OPSIMP) { 445 if (op->op == i) { 446 P((fc, FMTdPTR ", ", op - table)); 447 curalen++; 448 } 449 } else { 450 int opmtemp; 451 if ((opmtemp=mamask[op->op - OPSIMP])&SPFLG) { 452 if (i==NAME || i==ICON || i==TEMP || 453 i==OREG || i == REG || i == FCON) { 454 P((fc, FMTdPTR ", ", 455 op - table)); 456 curalen++; 457 } 458 } else if ((dope[i]&(opmtemp|ASGFLG))==opmtemp){ 459 P((fc, FMTdPTR ", ", op - table)); 460 curalen++; 461 } 462 } 463 } 464 if (curalen > mxalen) 465 mxalen = curalen; 466 P((fc, "-1 };\n")); 467 } 468 P((fc, "\n")); 469 470 P((fc, "int *qtable[] = { \n")); 471 for (i = 0; i <= MAXOP; i++) { 472 P((fc, " op%d,\n", i)); 473 } 474 P((fc, "};\n")); 475 P((fh, "#define MAXOPLEN %d\n", mxalen+1)); 476} 477