1 #include "gc.h" 2 3 int 4 swcmp(void *a1, 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 22 def = 0; 23 nc = 0; 24 for(c = cases; c->link != C; c = c->link) { 25 if(c->def) { 26 if(def) 27 diag(n, "more than one default in switch"); 28 def = c->label; 29 continue; 30 } 31 nc++; 32 } 33 34 iq = alloc(nc*sizeof(C1)); 35 q = iq; 36 for(c = cases; c->link != C; c = c->link) { 37 if(c->def) 38 continue; 39 q->label = c->label; 40 q->val = c->val; 41 q++; 42 } 43 qsort(iq, nc, sizeof(C1), swcmp); 44 if(debug['W']) 45 for(i=0; i<nc; i++) 46 print("case %2ld: = %.8lux\n", i, iq[i].val); 47 if(def == 0) 48 def = breakpc; 49 for(i=0; i<nc-1; i++) 50 if(iq[i].val == iq[i+1].val) 51 diag(n, "duplicate cases in switch %ld", iq[i].val); 52 swit1(iq, nc, def, n); 53 } 54 55 void 56 swit1(C1 *q, int nc, long def, Node *n) 57 { 58 C1 *r; 59 int i; 60 Prog *sp; 61 62 if(nc < 5) { 63 for(i=0; i<nc; i++) { 64 if(debug['W']) 65 print("case = %.8lux\n", q->val); 66 gopcode(OEQ, nodconst(q->val), n, Z); 67 patch(p, q->label); 68 q++; 69 } 70 gbranch(OGOTO); 71 patch(p, def); 72 return; 73 } 74 75 i = nc / 2; 76 r = q+i; 77 if(debug['W']) 78 print("case > %.8lux\n", r->val); 79 gopcode(OGT, nodconst(r->val), n, Z); 80 sp = p; 81 gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */ 82 patch(p, r->label); 83 swit1(q, i, def, n); 84 85 if(debug['W']) 86 print("case < %.8lux\n", r->val); 87 patch(sp, pc); 88 swit1(r+1, nc-i-1, def, n); 89 } 90 91 void 92 casf(void) 93 { 94 Case *c; 95 96 c = alloc(sizeof(*c)); 97 c->link = cases; 98 cases = c; 99 } 100 101 void 102 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 103 { 104 int sh; 105 long v; 106 Node *l; 107 108 /* 109 * n1 gets adjusted/masked value 110 * n2 gets address of cell 111 * n3 gets contents of cell 112 */ 113 l = b->left; 114 if(n2 != Z) { 115 regalloc(n1, l, nn); 116 reglcgen(n2, l, Z); 117 regalloc(n3, l, Z); 118 gopcode(OAS, n2, Z, n3); 119 gopcode(OAS, n3, Z, n1); 120 } else { 121 regalloc(n1, l, nn); 122 cgen(l, n1); 123 } 124 if(b->type->shift == 0 && typeu[b->type->etype]) { 125 v = ~0 + (1L << b->type->nbits); 126 gopcode2(OAND, nodconst(v), Z, n1); 127 } else { 128 sh = 32 - b->type->shift - b->type->nbits; 129 if(sh > 0) 130 gopcode(OASHL, nodconst(sh), Z, n1); 131 sh += b->type->shift; 132 if(sh > 0) 133 if(typeu[b->type->etype]) 134 gopcode(OLSHR, nodconst(sh), Z, n1); 135 else 136 gopcode(OASHR, nodconst(sh), Z, n1); 137 } 138 } 139 140 void 141 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 142 { 143 long v; 144 Node nod, *l; 145 int sh; 146 147 /* 148 * n1 has adjusted/masked value 149 * n2 has address of cell 150 * n3 has contents of cell 151 */ 152 l = b->left; 153 regalloc(&nod, l, Z); 154 v = ~0 + (1L << b->type->nbits); 155 gopcode2(OAND, nodconst(v), Z, n1); 156 gopcode(OAS, n1, Z, &nod); 157 if(nn != Z) 158 gopcode(OAS, n1, Z, nn); 159 sh = b->type->shift; 160 if(sh > 0) 161 gopcode(OASHL, nodconst(sh), Z, &nod); 162 v <<= sh; 163 gopcode2(OAND, nodconst(~v), Z, n3); 164 gopcode(OOR, n3, Z, &nod); 165 gopcode(OAS, &nod, Z, n2); 166 167 regfree(&nod); 168 regfree(n1); 169 regfree(n2); 170 regfree(n3); 171 } 172 173 long 174 outstring(char *s, long n) 175 { 176 long r; 177 178 if(suppress) 179 return nstring; 180 r = nstring; 181 while(n) { 182 string[mnstring] = *s++; 183 mnstring++; 184 nstring++; 185 if(mnstring >= NSNAME) { 186 gpseudo(ADATA, symstring, nodconst(0L)); 187 p->from.offset += nstring - NSNAME; 188 p->reg = NSNAME; 189 p->to.type = D_SCONST; 190 memmove(p->to.sval, string, NSNAME); 191 mnstring = 0; 192 } 193 n--; 194 } 195 return r; 196 } 197 198 long 199 outlstring(ushort *s, long n) 200 { 201 char buf[2]; 202 int c; 203 long r; 204 205 if(suppress) 206 return nstring; 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, vs; 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 vs = v; 268 regalloc(&nod2, n, Z); 269 270 loop: 271 switch(*p) { 272 case 0: 273 regfree(&nod2); 274 if(vs < 0) { 275 gopcode(OAS, &nod1, Z, &nod1); 276 gopcode(OSUB, &nod1, nodconst(0), nn); 277 } else 278 gopcode(OAS, &nod1, Z, nn); 279 /* 280 if(vs < 0) 281 gopcode(ONEG, &nod1, Z, &nod1); 282 gopcode(OAS, &nod1, Z, nn); 283 */ 284 regfree(&nod1); 285 return 1; 286 case '+': 287 o = OADD; 288 goto addsub; 289 case '-': 290 o = OSUB; 291 addsub: /* number is r,n,l */ 292 v = p[1] - '0'; 293 r = &nod1; 294 if(v&4) 295 r = &nod2; 296 n = &nod1; 297 if(v&2) 298 n = &nod2; 299 l = &nod1; 300 if(v&1) 301 l = &nod2; 302 gopcode(o, l, n, r); 303 break; 304 default: /* op is shiftcount, number is r,l */ 305 v = p[1] - '0'; 306 r = &nod1; 307 if(v&2) 308 r = &nod2; 309 l = &nod1; 310 if(v&1) 311 l = &nod2; 312 v = *p - 'a'; 313 if(v < 0 || v >= 32) { 314 diag(n, "mulcon unknown op: %c%c", p[0], p[1]); 315 break; 316 } 317 gopcode(OASHL, nodconst(v), l, r); 318 break; 319 } 320 p += 2; 321 goto loop; 322 } 323 324 void 325 nullwarn(Node *l, Node *r) 326 { 327 warn(Z, "result of operation not used"); 328 if(l != Z) 329 cgen(l, Z); 330 if(r != Z) 331 cgen(r, Z); 332 } 333 334 void 335 sextern(Sym *s, Node *a, long o, long w) 336 { 337 long e, lw; 338 339 for(e=0; e<w; e+=NSNAME) { 340 lw = NSNAME; 341 if(w-e < lw) 342 lw = w-e; 343 gpseudo(ADATA, s, nodconst(0)); 344 p->from.offset += o+e; 345 p->reg = lw; 346 p->to.type = D_SCONST; 347 memmove(p->to.sval, a->cstring+e, lw); 348 } 349 } 350 351 void 352 gextern(Sym *s, Node *a, long o, long w) 353 { 354 355 if(a->op == OCONST && typev[a->type->etype]) { 356 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 357 p->from.offset += o; 358 p->reg = 4; 359 gpseudo(ADATA, s, nod32const(a->vconst)); 360 p->from.offset += o + 4; 361 p->reg = 4; 362 return; 363 } 364 gpseudo(ADATA, s, a); 365 p->from.offset += o; 366 p->reg = w; 367 if(p->to.type == D_OREG) 368 p->to.type = D_CONST; 369 } 370 371 void zname(Biobuf*, Sym*, int); 372 char* zaddr(char*, Adr*, int); 373 void zwrite(Biobuf*, Prog*, int, int); 374 void outhist(Biobuf*); 375 376 void 377 zwrite(Biobuf *b, Prog *p, int sf, int st) 378 { 379 char bf[100], *bp; 380 381 bf[0] = p->as; 382 bf[1] = 14; 383 bf[2] = p->reg; 384 bf[3] = p->lineno; 385 bf[4] = p->lineno>>8; 386 bf[5] = p->lineno>>16; 387 bf[6] = p->lineno>>24; 388 bp = zaddr(bf+7, &p->from, sf); 389 bp = zaddr(bp, &p->to, st); 390 Bwrite(b, bf, bp-bf); 391 } 392 393 void 394 outcode(void) 395 { 396 struct { Sym *sym; short type; } h[NSYM]; 397 Prog *p; 398 Sym *s; 399 int sf, st, t, sym; 400 401 if(debug['S']) { 402 for(p = firstp; p != P; p = p->link) 403 if(p->as != ADATA && p->as != AGLOBL) 404 pc--; 405 for(p = firstp; p != P; p = p->link) { 406 print("%P\n", p); 407 if(p->as != ADATA && p->as != AGLOBL) 408 pc++; 409 } 410 } 411 outhist(&outbuf); 412 for(sym=0; sym<NSYM; sym++) { 413 h[sym].sym = S; 414 h[sym].type = 0; 415 } 416 sym = 1; 417 for(p = firstp; p != P; p = p->link) { 418 jackpot: 419 sf = 0; 420 s = p->from.sym; 421 while(s != S) { 422 sf = s->sym; 423 if(sf < 0 || sf >= NSYM) 424 sf = 0; 425 t = p->from.name; 426 if(h[sf].type == t) 427 if(h[sf].sym == s) 428 break; 429 s->sym = sym; 430 zname(&outbuf, s, t); 431 h[sym].sym = s; 432 h[sym].type = t; 433 sf = sym; 434 sym++; 435 if(sym >= NSYM) 436 sym = 1; 437 break; 438 } 439 st = 0; 440 s = p->to.sym; 441 while(s != S) { 442 st = s->sym; 443 if(st < 0 || st >= NSYM) 444 st = 0; 445 t = p->to.name; 446 if(h[st].type == t) 447 if(h[st].sym == s) 448 break; 449 s->sym = sym; 450 zname(&outbuf, s, t); 451 h[sym].sym = s; 452 h[sym].type = t; 453 st = sym; 454 sym++; 455 if(sym >= NSYM) 456 sym = 1; 457 if(st == sf) 458 goto jackpot; 459 break; 460 } 461 zwrite(&outbuf, p, sf, st); 462 } 463 firstp = P; 464 lastp = P; 465 } 466 467 void 468 outhist(Biobuf *b) 469 { 470 Hist *h; 471 char *p, *q, *op, c; 472 Prog pg; 473 int n; 474 475 pg = zprog; 476 pg.as = AHISTORY; 477 c = pathchar(); 478 for(h = hist; h != H; h = h->link) { 479 p = h->name; 480 op = 0; 481 /* on windows skip drive specifier in pathname */ 482 if(systemtype(Windows) && p && p[1] == ':'){ 483 p += 2; 484 c = *p; 485 } 486 if(p && p[0] != c && h->offset == 0 && pathname){ 487 /* on windows skip drive specifier in pathname */ 488 if(systemtype(Windows) && pathname[1] == ':') { 489 op = p; 490 p = pathname+2; 491 c = *p; 492 } else if(pathname[0] == c){ 493 op = p; 494 p = pathname; 495 } 496 } 497 while(p) { 498 q = utfrune(p, c); 499 if(q) { 500 n = q-p; 501 if(n == 0){ 502 n = 1; /* leading "/" */ 503 *p = '/'; /* don't emit "\" on windows */ 504 } 505 q++; 506 } else { 507 n = strlen(p); 508 q = 0; 509 } 510 if(n) { 511 Bputc(b, ANAME); 512 Bputc(b, D_FILE); 513 Bputc(b, 1); 514 Bputc(b, '<'); 515 Bwrite(b, p, n); 516 Bputc(b, 0); 517 } 518 p = q; 519 if(p == 0 && op) { 520 p = op; 521 op = 0; 522 } 523 } 524 pg.lineno = h->line; 525 pg.to.type = zprog.to.type; 526 pg.to.offset = h->offset; 527 if(h->offset) 528 pg.to.type = D_CONST; 529 530 zwrite(b, &pg, 0, 0); 531 } 532 } 533 534 void 535 zname(Biobuf *b, Sym *s, int t) 536 { 537 char *n, bf[7]; 538 ulong sig; 539 540 n = s->name; 541 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ 542 sig = sign(s); 543 bf[0] = ASIGNAME; 544 bf[1] = sig; 545 bf[2] = sig>>8; 546 bf[3] = sig>>16; 547 bf[4] = sig>>24; 548 bf[5] = t; 549 bf[6] = s->sym; 550 Bwrite(b, bf, 7); 551 s->sig = SIGDONE; 552 } 553 else{ 554 bf[0] = ANAME; 555 bf[1] = t; /* type */ 556 bf[2] = s->sym; /* sym */ 557 Bwrite(b, bf, 3); 558 } 559 Bwrite(b, n, strlen(n)+1); 560 } 561 562 char* 563 zaddr(char *bp, Adr *a, int s) 564 { 565 long l; 566 Ieee e; 567 568 bp[0] = a->type; 569 bp[1] = a->reg; 570 bp[2] = s; 571 bp[3] = a->name; 572 bp += 4; 573 switch(a->type) { 574 default: 575 diag(Z, "unknown type %d in zaddr", a->type); 576 577 case D_NONE: 578 case D_REG: 579 case D_FREG: 580 case D_PSR: 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 w = 1; /* little endian no adjustment */ 691 break; 692 693 case Aarg2: /* width of a parameter */ 694 o += t->width; 695 w = SZ_LONG; 696 break; 697 698 case Aaut3: /* total allign of automatic */ 699 o = align(o, t, Ael2); 700 o = align(o, t, Ael1); 701 w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */ 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 = round(v, SZ_LONG); 714 if(v > max) 715 return v; 716 return max; 717 } 718