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*, char*, int, 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 zname(&outbuf, s->name, t, sym); 427 s->sym = sym; 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 zname(&outbuf, s->name, t, sym); 447 s->sym = sym; 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 if(p && p[0] != c && h->offset == 0 && pathname){ 479 /* on windows skip drive specifier in pathname */ 480 if(systemtype(Windows) && pathname[2] == c) { 481 op = p; 482 p = pathname+2; 483 *p = '/'; 484 } else if(pathname[0] == c){ 485 op = p; 486 p = pathname; 487 } 488 } 489 while(p) { 490 q = utfrune(p, c); 491 if(q) { 492 n = q-p; 493 if(n == 0) 494 n = 1; /* leading "/" */ 495 q++; 496 } else { 497 n = strlen(p); 498 q = 0; 499 } 500 if(n) { 501 Bputc(b, ANAME); 502 Bputc(b, D_FILE); 503 Bputc(b, 1); 504 Bputc(b, '<'); 505 Bwrite(b, p, n); 506 Bputc(b, 0); 507 } 508 p = q; 509 if(p == 0 && op) { 510 p = op; 511 op = 0; 512 } 513 } 514 pg.lineno = h->line; 515 pg.to.type = zprog.to.type; 516 pg.to.offset = h->offset; 517 if(h->offset) 518 pg.to.type = D_CONST; 519 520 zwrite(b, &pg, 0, 0); 521 } 522 } 523 524 void 525 zname(Biobuf *b, char *n, int t, int s) 526 { 527 char bf[3]; 528 529 bf[0] = ANAME; 530 bf[1] = t; /* type */ 531 bf[2] = s; /* sym */ 532 Bwrite(b, bf, 3); 533 Bwrite(b, n, strlen(n)+1); 534 } 535 536 char* 537 zaddr(char *bp, Adr *a, int s) 538 { 539 long l; 540 Ieee e; 541 542 bp[0] = a->type; 543 bp[1] = a->reg; 544 bp[2] = s; 545 bp[3] = a->name; 546 bp += 4; 547 switch(a->type) { 548 default: 549 diag(Z, "unknown type %d in zaddr", a->type); 550 551 case D_NONE: 552 case D_REG: 553 case D_FREG: 554 case D_MREG: 555 case D_FCREG: 556 case D_LO: 557 case D_HI: 558 break; 559 560 case D_OREG: 561 case D_CONST: 562 case D_BRANCH: 563 l = a->offset; 564 bp[0] = l; 565 bp[1] = l>>8; 566 bp[2] = l>>16; 567 bp[3] = l>>24; 568 bp += 4; 569 break; 570 571 case D_SCONST: 572 memmove(bp, a->sval, NSNAME); 573 bp += NSNAME; 574 break; 575 576 case D_FCONST: 577 ieeedtod(&e, a->dval); 578 l = e.l; 579 bp[0] = l; 580 bp[1] = l>>8; 581 bp[2] = l>>16; 582 bp[3] = l>>24; 583 bp += 4; 584 l = e.h; 585 bp[0] = l; 586 bp[1] = l>>8; 587 bp[2] = l>>16; 588 bp[3] = l>>24; 589 bp += 4; 590 break; 591 } 592 return bp; 593 } 594 595 void 596 ieeedtod(Ieee *ieee, double native) 597 { 598 double fr, ho, f; 599 int exp; 600 601 if(native < 0) { 602 ieeedtod(ieee, -native); 603 ieee->h |= 0x80000000L; 604 return; 605 } 606 if(native == 0) { 607 ieee->l = 0; 608 ieee->h = 0; 609 return; 610 } 611 fr = frexp(native, &exp); 612 f = 2097152L; /* shouldnt use fp constants here */ 613 fr = modf(fr*f, &ho); 614 ieee->h = ho; 615 ieee->h &= 0xfffffL; 616 ieee->h |= (exp+1022L) << 20; 617 f = 65536L; 618 fr = modf(fr*f, &ho); 619 ieee->l = ho; 620 ieee->l <<= 16; 621 ieee->l |= (long)(fr*f); 622 } 623 624 long 625 align(long i, Type *t, int op) 626 { 627 long o; 628 Type *v; 629 int w; 630 631 o = i; 632 w = 1; 633 switch(op) { 634 default: 635 diag(Z, "unknown align opcode %d", op); 636 break; 637 638 case Asu2: /* padding at end of a struct */ 639 w = SZ_LONG; 640 break; 641 642 case Ael1: /* initial allign of struct element */ 643 for(v=t; v->etype==TARRAY; v=v->link) 644 ; 645 w = ewidth[v->etype]; 646 if(w <= 0 || w >= SZ_LONG) 647 w = SZ_LONG; 648 break; 649 650 case Ael2: /* width of a struct element */ 651 o += t->width; 652 break; 653 654 case Aarg0: /* initial passbyptr argument in arg list */ 655 if(typesuv[t->etype]) { 656 o = align(o, types[TIND], Aarg1); 657 o = align(o, types[TIND], Aarg2); 658 } 659 break; 660 661 case Aarg1: /* initial allign of parameter */ 662 w = ewidth[t->etype]; 663 if(w <= 0 || w >= SZ_LONG) { 664 w = SZ_LONG; 665 break; 666 } 667 o += SZ_LONG - w; /* big endian adjustment */ 668 w = 1; 669 break; 670 671 case Aarg2: /* width of a parameter */ 672 o += t->width; 673 w = SZ_LONG; 674 break; 675 676 case Aaut3: /* total allign of automatic */ 677 o = align(o, t, Ael1); 678 o = align(o, t, Ael2); 679 break; 680 } 681 o = round(o, w); 682 if(debug['A']) 683 print("align %s %ld %T = %ld\n", bnames[op], i, t, o); 684 return o; 685 } 686 687 long 688 maxround(long max, long v) 689 { 690 v += SZ_LONG-1; 691 if(v > max) 692 max = round(v, SZ_LONG); 693 return max; 694 } 695