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