1 #include "gc.h" 2 3 void 4 swit1(C1 *q, int nc, long def, Node *n) 5 { 6 Node tn; 7 8 regalloc(&tn, ®node, Z); 9 swit2(q, nc, def, n, &tn); 10 regfree(&tn); 11 } 12 13 void 14 swit2(C1 *q, int nc, long def, Node *n, Node *tn) 15 { 16 C1 *r; 17 int i; 18 long v; 19 Prog *sp; 20 21 if(nc >= 3) { 22 i = (q+nc-1)->val - (q+0)->val; 23 if(i > 0 && i < nc*2) 24 goto direct; 25 } 26 if(nc < 5) { 27 for(i=0; i<nc; i++) { 28 if(debug['K']) 29 print("case = %.8llux\n", q->val); 30 gopcode(OEQ, nodconst(q->val), n, Z); 31 patch(p, q->label); 32 q++; 33 } 34 gbranch(OGOTO); 35 patch(p, def); 36 return; 37 } 38 39 i = nc / 2; 40 r = q+i; 41 if(debug['K']) 42 print("case > %.8llux\n", r->val); 43 gopcode(OGT, nodconst(r->val), n, Z); 44 sp = p; 45 gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */ 46 patch(p, r->label); 47 swit2(q, i, def, n, tn); 48 49 if(debug['K']) 50 print("case < %.8llux\n", r->val); 51 patch(sp, pc); 52 swit2(r+1, nc-i-1, def, n, tn); 53 return; 54 55 direct: 56 v = q->val; 57 if(v != 0) 58 gopcode(OSUB, nodconst(v), Z, n); 59 gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z); 60 patch(p, def); 61 for(i=0; i<nc; i++) { 62 if(debug['K']) 63 print("case = %.8llux\n", q->val); 64 while(q->val != v) { 65 nextpc(); 66 p->as = ABCASE; 67 patch(p, def); 68 v++; 69 } 70 nextpc(); 71 p->as = ABCASE; 72 patch(p, q->label); 73 q++; 74 v++; 75 } 76 gbranch(OGOTO); /* so that regopt() won't be confused */ 77 patch(p, def); 78 } 79 80 void 81 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 82 { 83 int sh; 84 long v; 85 Node *l; 86 87 /* 88 * n1 gets adjusted/masked value 89 * n2 gets address of cell 90 * n3 gets contents of cell 91 */ 92 l = b->left; 93 if(n2 != Z) { 94 regalloc(n1, l, nn); 95 reglcgen(n2, l, Z); 96 regalloc(n3, l, Z); 97 gopcode(OAS, n2, Z, n3); 98 gopcode(OAS, n3, Z, n1); 99 } else { 100 regalloc(n1, l, nn); 101 cgen(l, n1); 102 } 103 if(b->type->shift == 0 && typeu[b->type->etype]) { 104 v = ~0 + (1L << b->type->nbits); 105 gopcode(OAND, nodconst(v), Z, n1); 106 } else { 107 sh = 32 - b->type->shift - b->type->nbits; 108 if(sh > 0) 109 gopcode(OASHL, nodconst(sh), Z, n1); 110 sh += b->type->shift; 111 if(sh > 0) 112 if(typeu[b->type->etype]) 113 gopcode(OLSHR, nodconst(sh), Z, n1); 114 else 115 gopcode(OASHR, nodconst(sh), Z, n1); 116 } 117 } 118 119 void 120 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 121 { 122 long v; 123 Node nod, *l; 124 int sh; 125 126 /* 127 * n1 has adjusted/masked value 128 * n2 has address of cell 129 * n3 has contents of cell 130 */ 131 l = b->left; 132 regalloc(&nod, l, Z); 133 v = ~0 + (1L << b->type->nbits); 134 gopcode(OAND, nodconst(v), Z, n1); 135 gopcode(OAS, n1, Z, &nod); 136 if(nn != Z) 137 gopcode(OAS, n1, Z, nn); 138 sh = b->type->shift; 139 if(sh > 0) 140 gopcode(OASHL, nodconst(sh), Z, &nod); 141 v <<= sh; 142 gopcode(OAND, nodconst(~v), Z, n3); 143 gopcode(OOR, n3, Z, &nod); 144 gopcode(OAS, &nod, Z, n2); 145 146 regfree(&nod); 147 regfree(n1); 148 regfree(n2); 149 regfree(n3); 150 } 151 152 long 153 outstring(char *s, long n) 154 { 155 long r; 156 157 if(suppress) 158 return nstring; 159 r = nstring; 160 while(n) { 161 string[mnstring] = *s++; 162 mnstring++; 163 nstring++; 164 if(mnstring >= NSNAME) { 165 gpseudo(ADATA, symstring, nodconst(0L)); 166 p->from.offset += nstring - NSNAME; 167 p->reg = NSNAME; 168 p->to.type = D_SCONST; 169 memmove(p->to.sval, string, NSNAME); 170 mnstring = 0; 171 } 172 n--; 173 } 174 return r; 175 } 176 177 int 178 mulcon(Node *n, Node *nn) 179 { 180 Node *l, *r, nod1, nod2; 181 Multab *m; 182 long v, vs; 183 int o; 184 char code[sizeof(m->code)+2], *p; 185 186 if(typefd[n->type->etype]) 187 return 0; 188 l = n->left; 189 r = n->right; 190 if(l->op == OCONST) { 191 l = r; 192 r = n->left; 193 } 194 if(r->op != OCONST) 195 return 0; 196 v = convvtox(r->vconst, n->type->etype); 197 if(v != r->vconst) { 198 if(debug['M']) 199 print("%L multiply conv: %lld\n", n->lineno, r->vconst); 200 return 0; 201 } 202 m = mulcon0(v); 203 if(!m) { 204 if(debug['M']) 205 print("%L multiply table: %lld\n", n->lineno, r->vconst); 206 return 0; 207 } 208 if(debug['M'] && debug['v']) 209 print("%L multiply: %ld\n", n->lineno, v); 210 211 memmove(code, m->code, sizeof(m->code)); 212 code[sizeof(m->code)] = 0; 213 214 p = code; 215 if(p[1] == 'i') 216 p += 2; 217 regalloc(&nod1, n, nn); 218 cgen(l, &nod1); 219 vs = v; 220 regalloc(&nod2, n, Z); 221 222 loop: 223 switch(*p) { 224 case 0: 225 regfree(&nod2); 226 if(vs < 0) { 227 gopcode(OAS, &nod1, Z, &nod1); 228 gopcode(OSUB, &nod1, nodconst(0), nn); 229 } else 230 gopcode(OAS, &nod1, Z, nn); 231 regfree(&nod1); 232 return 1; 233 case '+': 234 o = OADD; 235 goto addsub; 236 case '-': 237 o = OSUB; 238 addsub: /* number is r,n,l */ 239 v = p[1] - '0'; 240 r = &nod1; 241 if(v&4) 242 r = &nod2; 243 n = &nod1; 244 if(v&2) 245 n = &nod2; 246 l = &nod1; 247 if(v&1) 248 l = &nod2; 249 gopcode(o, l, n, r); 250 break; 251 default: /* op is shiftcount, number is r,l */ 252 v = p[1] - '0'; 253 r = &nod1; 254 if(v&2) 255 r = &nod2; 256 l = &nod1; 257 if(v&1) 258 l = &nod2; 259 v = *p - 'a'; 260 if(v < 0 || v >= 32) { 261 diag(n, "mulcon unknown op: %c%c", p[0], p[1]); 262 break; 263 } 264 gopcode(OASHL, nodconst(v), l, r); 265 break; 266 } 267 p += 2; 268 goto loop; 269 } 270 271 void 272 gextern(Sym *s, Node *a, long o, long w) 273 { 274 275 if(a->op == OCONST && typev[a->type->etype]) { 276 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 277 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 278 else 279 gpseudo(ADATA, s, nod32const(a->vconst)); 280 p->from.offset += o; 281 p->reg = 4; 282 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 283 gpseudo(ADATA, s, nod32const(a->vconst)); 284 else 285 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 286 p->from.offset += o + 4; 287 p->reg = 4; 288 return; 289 } 290 gpseudo(ADATA, s, a); 291 p->from.offset += o; 292 p->reg = w; 293 if(p->to.type == D_OREG) 294 p->to.type = D_CONST; 295 } 296 297 void zname(Biobuf*, Sym*, int); 298 char* zaddr(char*, Adr*, int); 299 void zwrite(Biobuf*, Prog*, int, int); 300 void outhist(Biobuf*); 301 302 void 303 zwrite(Biobuf *b, Prog *p, int sf, int st) 304 { 305 char bf[100], *bp; 306 307 bf[0] = p->as; 308 bf[1] = p->scond; 309 bf[2] = p->reg; 310 bf[3] = p->lineno; 311 bf[4] = p->lineno>>8; 312 bf[5] = p->lineno>>16; 313 bf[6] = p->lineno>>24; 314 bp = zaddr(bf+7, &p->from, sf); 315 bp = zaddr(bp, &p->to, st); 316 Bwrite(b, bf, bp-bf); 317 } 318 319 void 320 outcode(void) 321 { 322 struct { Sym *sym; short type; } h[NSYM]; 323 Prog *p; 324 Sym *s; 325 int sf, st, t, sym; 326 327 if(debug['S']) { 328 for(p = firstp; p != P; p = p->link) 329 if(p->as != ADATA && p->as != AGLOBL) 330 pc--; 331 for(p = firstp; p != P; p = p->link) { 332 print("%P\n", p); 333 if(p->as != ADATA && p->as != AGLOBL) 334 pc++; 335 } 336 } 337 outhist(&outbuf); 338 for(sym=0; sym<NSYM; sym++) { 339 h[sym].sym = S; 340 h[sym].type = 0; 341 } 342 sym = 1; 343 for(p = firstp; p != P; p = p->link) { 344 jackpot: 345 sf = 0; 346 s = p->from.sym; 347 while(s != S) { 348 sf = s->sym; 349 if(sf < 0 || sf >= NSYM) 350 sf = 0; 351 t = p->from.name; 352 if(h[sf].type == t) 353 if(h[sf].sym == s) 354 break; 355 s->sym = sym; 356 zname(&outbuf, s, t); 357 h[sym].sym = s; 358 h[sym].type = t; 359 sf = sym; 360 sym++; 361 if(sym >= NSYM) 362 sym = 1; 363 break; 364 } 365 st = 0; 366 s = p->to.sym; 367 while(s != S) { 368 st = s->sym; 369 if(st < 0 || st >= NSYM) 370 st = 0; 371 t = p->to.name; 372 if(h[st].type == t) 373 if(h[st].sym == s) 374 break; 375 s->sym = sym; 376 zname(&outbuf, s, t); 377 h[sym].sym = s; 378 h[sym].type = t; 379 st = sym; 380 sym++; 381 if(sym >= NSYM) 382 sym = 1; 383 if(st == sf) 384 goto jackpot; 385 break; 386 } 387 zwrite(&outbuf, p, sf, st); 388 } 389 firstp = P; 390 lastp = P; 391 } 392 393 void 394 outhist(Biobuf *b) 395 { 396 Hist *h; 397 char *p, *q, *op, c; 398 Prog pg; 399 int n; 400 401 pg = zprog; 402 pg.as = AHISTORY; 403 c = pathchar(); 404 for(h = hist; h != H; h = h->link) { 405 p = h->name; 406 op = 0; 407 /* on windows skip drive specifier in pathname */ 408 if(systemtype(Windows) && p && p[1] == ':'){ 409 p += 2; 410 c = *p; 411 } 412 if(p && p[0] != c && h->offset == 0 && pathname){ 413 /* on windows skip drive specifier in pathname */ 414 if(systemtype(Windows) && pathname[1] == ':') { 415 op = p; 416 p = pathname+2; 417 c = *p; 418 } else if(pathname[0] == c){ 419 op = p; 420 p = pathname; 421 } 422 } 423 while(p) { 424 q = utfrune(p, c); 425 if(q) { 426 n = q-p; 427 if(n == 0){ 428 n = 1; /* leading "/" */ 429 *p = '/'; /* don't emit "\" on windows */ 430 } 431 q++; 432 } else { 433 n = strlen(p); 434 q = 0; 435 } 436 if(n) { 437 Bputc(b, ANAME); 438 Bputc(b, D_FILE); 439 Bputc(b, 1); 440 Bputc(b, '<'); 441 Bwrite(b, p, n); 442 Bputc(b, 0); 443 } 444 p = q; 445 if(p == 0 && op) { 446 p = op; 447 op = 0; 448 } 449 } 450 pg.lineno = h->line; 451 pg.to.type = zprog.to.type; 452 pg.to.offset = h->offset; 453 if(h->offset) 454 pg.to.type = D_CONST; 455 456 zwrite(b, &pg, 0, 0); 457 } 458 } 459 460 void 461 zname(Biobuf *b, Sym *s, int t) 462 { 463 char *n, bf[7]; 464 ulong sig; 465 466 n = s->name; 467 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ 468 sig = sign(s); 469 bf[0] = ASIGNAME; 470 bf[1] = sig; 471 bf[2] = sig>>8; 472 bf[3] = sig>>16; 473 bf[4] = sig>>24; 474 bf[5] = t; 475 bf[6] = s->sym; 476 Bwrite(b, bf, 7); 477 s->sig = SIGDONE; 478 } 479 else{ 480 bf[0] = ANAME; 481 bf[1] = t; /* type */ 482 bf[2] = s->sym; /* sym */ 483 Bwrite(b, bf, 3); 484 } 485 Bwrite(b, n, strlen(n)+1); 486 } 487 488 char* 489 zaddr(char *bp, Adr *a, int s) 490 { 491 long l; 492 Ieee e; 493 494 bp[0] = a->type; 495 bp[1] = a->reg; 496 bp[2] = s; 497 bp[3] = a->name; 498 bp += 4; 499 switch(a->type) { 500 default: 501 diag(Z, "unknown type %d in zaddr", a->type); 502 503 case D_NONE: 504 case D_REG: 505 case D_FREG: 506 case D_PSR: 507 break; 508 509 case D_OREG: 510 case D_CONST: 511 case D_BRANCH: 512 case D_SHIFT: 513 l = a->offset; 514 bp[0] = l; 515 bp[1] = l>>8; 516 bp[2] = l>>16; 517 bp[3] = l>>24; 518 bp += 4; 519 break; 520 521 case D_SCONST: 522 memmove(bp, a->sval, NSNAME); 523 bp += NSNAME; 524 break; 525 526 case D_FCONST: 527 ieeedtod(&e, a->dval); 528 l = e.l; 529 bp[0] = l; 530 bp[1] = l>>8; 531 bp[2] = l>>16; 532 bp[3] = l>>24; 533 bp += 4; 534 l = e.h; 535 bp[0] = l; 536 bp[1] = l>>8; 537 bp[2] = l>>16; 538 bp[3] = l>>24; 539 bp += 4; 540 break; 541 } 542 return bp; 543 } 544 545 long 546 align(long i, Type *t, int op) 547 { 548 long o; 549 Type *v; 550 int w; 551 552 o = i; 553 w = 1; 554 switch(op) { 555 default: 556 diag(Z, "unknown align opcode %d", op); 557 break; 558 559 case Asu2: /* padding at end of a struct */ 560 w = SZ_LONG; 561 if(packflg) 562 w = packflg; 563 break; 564 565 case Ael1: /* initial align of struct element */ 566 for(v=t; v->etype==TARRAY; v=v->link) 567 ; 568 w = ewidth[v->etype]; 569 if(w <= 0 || w >= SZ_LONG) 570 w = SZ_LONG; 571 if(packflg) 572 w = packflg; 573 break; 574 575 case Ael2: /* width of a struct element */ 576 o += t->width; 577 break; 578 579 case Aarg0: /* initial passbyptr argument in arg list */ 580 if(typesuv[t->etype]) { 581 o = align(o, types[TIND], Aarg1); 582 o = align(o, types[TIND], Aarg2); 583 } 584 break; 585 586 case Aarg1: /* initial align of parameter */ 587 w = ewidth[t->etype]; 588 if(w <= 0 || w >= SZ_LONG) { 589 w = SZ_LONG; 590 break; 591 } 592 w = 1; /* little endian no adjustment */ 593 break; 594 595 case Aarg2: /* width of a parameter */ 596 o += t->width; 597 w = SZ_LONG; 598 break; 599 600 case Aaut3: /* total align of automatic */ 601 o = align(o, t, Ael2); 602 o = align(o, t, Ael1); 603 w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */ 604 break; 605 } 606 o = round(o, w); 607 if(debug['A']) 608 print("align %s %ld %T = %ld\n", bnames[op], i, t, o); 609 return o; 610 } 611 612 long 613 maxround(long max, long v) 614 { 615 v = round(v, SZ_LONG); 616 if(v > max) 617 return v; 618 return max; 619 } 620