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