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 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 349 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 350 else 351 gpseudo(ADATA, s, nod32const(a->vconst)); 352 p->from.offset += o; 353 p->reg = 4; 354 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 355 gpseudo(ADATA, s, nod32const(a->vconst)); 356 else 357 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 358 p->from.offset += o + 4; 359 p->reg = 4; 360 return; 361 } 362 gpseudo(ADATA, s, a); 363 p->from.offset += o; 364 p->reg = w; 365 if(p->to.type == D_OREG) 366 p->to.type = D_CONST; 367 } 368 369 void zname(Biobuf*, Sym*, int); 370 char* zaddr(char*, Adr*, int); 371 void zwrite(Biobuf*, Prog*, int, int); 372 void outhist(Biobuf*); 373 374 void 375 zwrite(Biobuf *b, Prog *p, int sf, int st) 376 { 377 char bf[100], *bp; 378 379 bf[0] = p->as; 380 bf[1] = p->reg; 381 bf[2] = p->lineno; 382 bf[3] = p->lineno>>8; 383 bf[4] = p->lineno>>16; 384 bf[5] = p->lineno>>24; 385 bp = zaddr(bf+6, &p->from, sf); 386 bp = zaddr(bp, &p->to, st); 387 Bwrite(b, bf, bp-bf); 388 } 389 390 void 391 outcode(void) 392 { 393 struct { Sym *sym; short type; } h[NSYM]; 394 Prog *p; 395 Sym *s; 396 int sf, st, t, sym; 397 398 if(debug['S']) { 399 for(p = firstp; p != P; p = p->link) 400 if(p->as != ADATA && p->as != AGLOBL) 401 pc--; 402 for(p = firstp; p != P; p = p->link) { 403 print("%P\n", p); 404 if(p->as != ADATA && p->as != AGLOBL) 405 pc++; 406 } 407 } 408 outhist(&outbuf); 409 for(sym=0; sym<NSYM; sym++) { 410 h[sym].sym = S; 411 h[sym].type = 0; 412 } 413 sym = 1; 414 for(p = firstp; p != P; p = p->link) { 415 jackpot: 416 sf = 0; 417 s = p->from.sym; 418 while(s != S) { 419 sf = s->sym; 420 if(sf < 0 || sf >= NSYM) 421 sf = 0; 422 t = p->from.name; 423 if(h[sf].type == t) 424 if(h[sf].sym == s) 425 break; 426 s->sym = sym; 427 zname(&outbuf, s, t); 428 h[sym].sym = s; 429 h[sym].type = t; 430 sf = sym; 431 sym++; 432 if(sym >= NSYM) 433 sym = 1; 434 break; 435 } 436 st = 0; 437 s = p->to.sym; 438 while(s != S) { 439 st = s->sym; 440 if(st < 0 || st >= NSYM) 441 st = 0; 442 t = p->to.name; 443 if(h[st].type == t) 444 if(h[st].sym == s) 445 break; 446 s->sym = sym; 447 zname(&outbuf, s, t); 448 h[sym].sym = s; 449 h[sym].type = t; 450 st = sym; 451 sym++; 452 if(sym >= NSYM) 453 sym = 1; 454 if(st == sf) 455 goto jackpot; 456 break; 457 } 458 zwrite(&outbuf, p, sf, st); 459 } 460 firstp = P; 461 lastp = P; 462 } 463 464 void 465 outhist(Biobuf *b) 466 { 467 Hist *h; 468 char *p, *q, *op, c; 469 Prog pg; 470 int n; 471 472 pg = zprog; 473 pg.as = AHISTORY; 474 c = pathchar(); 475 for(h = hist; h != H; h = h->link) { 476 p = h->name; 477 op = 0; 478 /* on windows skip drive specifier in pathname */ 479 if(systemtype(Windows) && p && p[1] == ':'){ 480 p += 2; 481 c = *p; 482 } 483 if(p && p[0] != c && h->offset == 0 && pathname){ 484 /* on windows skip drive specifier in pathname */ 485 if(systemtype(Windows) && pathname[1] == ':') { 486 op = p; 487 p = pathname+2; 488 c = *p; 489 } else if(pathname[0] == c){ 490 op = p; 491 p = pathname; 492 } 493 } 494 while(p) { 495 q = utfrune(p, c); 496 if(q) { 497 n = q-p; 498 if(n == 0){ 499 n = 1; /* leading "/" */ 500 *p = '/'; /* don't emit "\" on windows */ 501 } 502 q++; 503 } else { 504 n = strlen(p); 505 q = 0; 506 } 507 if(n) { 508 Bputc(b, ANAME); 509 Bputc(b, D_FILE); 510 Bputc(b, 1); 511 Bputc(b, '<'); 512 Bwrite(b, p, n); 513 Bputc(b, 0); 514 } 515 p = q; 516 if(p == 0 && op) { 517 p = op; 518 op = 0; 519 } 520 } 521 pg.lineno = h->line; 522 pg.to.type = zprog.to.type; 523 pg.to.offset = h->offset; 524 if(h->offset) 525 pg.to.type = D_CONST; 526 527 zwrite(b, &pg, 0, 0); 528 } 529 } 530 531 void 532 zname(Biobuf *b, Sym *s, int t) 533 { 534 char *n, bf[7]; 535 ulong sig; 536 537 n = s->name; 538 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ 539 sig = sign(s); 540 bf[0] = ASIGNAME; 541 bf[1] = sig; 542 bf[2] = sig>>8; 543 bf[3] = sig>>16; 544 bf[4] = sig>>24; 545 bf[5] = t; 546 bf[6] = s->sym; 547 Bwrite(b, bf, 7); 548 s->sig = SIGDONE; 549 } 550 else{ 551 bf[0] = ANAME; 552 bf[1] = t; /* type */ 553 bf[2] = s->sym; /* sym */ 554 Bwrite(b, bf, 3); 555 } 556 Bwrite(b, n, strlen(n)+1); 557 } 558 559 char* 560 zaddr(char *bp, Adr *a, int s) 561 { 562 long l; 563 Ieee e; 564 565 bp[0] = a->type; 566 bp[1] = a->reg; 567 bp[2] = s; 568 bp[3] = a->name; 569 bp += 4; 570 switch(a->type) { 571 default: 572 diag(Z, "unknown type %d in zaddr", a->type); 573 574 case D_NONE: 575 case D_REG: 576 case D_FREG: 577 case D_MREG: 578 case D_FCREG: 579 case D_LO: 580 case D_HI: 581 break; 582 583 case D_OREG: 584 case D_CONST: 585 case D_BRANCH: 586 l = a->offset; 587 bp[0] = l; 588 bp[1] = l>>8; 589 bp[2] = l>>16; 590 bp[3] = l>>24; 591 bp += 4; 592 break; 593 594 case D_SCONST: 595 memmove(bp, a->sval, NSNAME); 596 bp += NSNAME; 597 break; 598 599 case D_FCONST: 600 ieeedtod(&e, a->dval); 601 l = e.l; 602 bp[0] = l; 603 bp[1] = l>>8; 604 bp[2] = l>>16; 605 bp[3] = l>>24; 606 bp += 4; 607 l = e.h; 608 bp[0] = l; 609 bp[1] = l>>8; 610 bp[2] = l>>16; 611 bp[3] = l>>24; 612 bp += 4; 613 break; 614 } 615 return bp; 616 } 617 618 void 619 ieeedtod(Ieee *ieee, double native) 620 { 621 double fr, ho, f; 622 int exp; 623 624 if(native < 0) { 625 ieeedtod(ieee, -native); 626 ieee->h |= 0x80000000L; 627 return; 628 } 629 if(native == 0) { 630 ieee->l = 0; 631 ieee->h = 0; 632 return; 633 } 634 fr = frexp(native, &exp); 635 f = 2097152L; /* shouldnt use fp constants here */ 636 fr = modf(fr*f, &ho); 637 ieee->h = ho; 638 ieee->h &= 0xfffffL; 639 ieee->h |= (exp+1022L) << 20; 640 f = 65536L; 641 fr = modf(fr*f, &ho); 642 ieee->l = ho; 643 ieee->l <<= 16; 644 ieee->l |= (long)(fr*f); 645 } 646 647 long 648 align(long i, Type *t, int op) 649 { 650 long o; 651 Type *v; 652 int w; 653 654 o = i; 655 w = 1; 656 switch(op) { 657 default: 658 diag(Z, "unknown align opcode %d", op); 659 break; 660 661 case Asu2: /* padding at end of a struct */ 662 w = SZ_LONG; 663 break; 664 665 case Ael1: /* initial allign of struct element */ 666 for(v=t; v->etype==TARRAY; v=v->link) 667 ; 668 w = ewidth[v->etype]; 669 if(w <= 0 || w >= SZ_LONG) 670 w = SZ_LONG; 671 break; 672 673 case Ael2: /* width of a struct element */ 674 o += t->width; 675 break; 676 677 case Aarg0: /* initial passbyptr argument in arg list */ 678 if(typesuv[t->etype]) { 679 o = align(o, types[TIND], Aarg1); 680 o = align(o, types[TIND], Aarg2); 681 } 682 break; 683 684 case Aarg1: /* initial allign of parameter */ 685 w = ewidth[t->etype]; 686 if(w <= 0 || w >= SZ_LONG) { 687 w = SZ_LONG; 688 break; 689 } 690 o += SZ_LONG - w; /* big endian adjustment */ 691 w = 1; 692 break; 693 694 case Aarg2: /* width of a parameter */ 695 o += t->width; 696 w = SZ_LONG; 697 break; 698 699 case Aaut3: /* total allign of automatic */ 700 o = align(o, t, Ael1); 701 o = align(o, t, Ael2); 702 break; 703 } 704 o = round(o, w); 705 if(debug['A']) 706 print("align %s %ld %T = %ld\n", bnames[op], i, t, o); 707 return o; 708 } 709 710 long 711 maxround(long max, long v) 712 { 713 v += SZ_LONG-1; 714 if(v > max) 715 max = round(v, SZ_LONG); 716 return max; 717 } 718