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