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