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