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