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