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 gextern(Sym *s, Node *a, long o, long w) 244 { 245 if(a->op == OCONST && typev[a->type->etype]) { 246 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 247 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 248 else 249 gpseudo(ADATA, s, nod32const(a->vconst)); 250 p->from.offset += o; 251 p->reg = 4; 252 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 253 gpseudo(ADATA, s, nod32const(a->vconst)); 254 else 255 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 256 p->from.offset += o + 4; 257 p->reg = 4; 258 return; 259 } 260 gpseudo(ADATA, s, a); 261 p->from.offset += o; 262 p->reg = w; 263 if(p->to.type == D_OREG) 264 p->to.type = D_CONST; 265 } 266 267 void zname(Biobuf*, Sym*, int); 268 char* zaddr(char*, Adr*, int); 269 void zwrite(Biobuf*, Prog*, int, int); 270 void outhist(Biobuf*); 271 272 void 273 outcode(void) 274 { 275 struct { Sym *sym; short type; } h[NSYM]; 276 Prog *p; 277 Sym *s; 278 int sf, st, t, sym; 279 280 if(debug['S']) { 281 for(p = firstp; p != P; p = p->link) 282 if(p->as != ADATA && p->as != AGLOBL) 283 pc--; 284 for(p = firstp; p != P; p = p->link) { 285 print("%P\n", p); 286 if(p->as != ADATA && p->as != AGLOBL) 287 pc++; 288 } 289 } 290 outhist(&outbuf); 291 for(sym=0; sym<NSYM; sym++) { 292 h[sym].sym = S; 293 h[sym].type = 0; 294 } 295 sym = 1; 296 for(p = firstp; p != P; p = p->link) { 297 jackpot: 298 sf = 0; 299 s = p->from.sym; 300 while(s != S) { 301 sf = s->sym; 302 if(sf < 0 || sf >= NSYM) 303 sf = 0; 304 t = p->from.name; 305 if(h[sf].type == t) 306 if(h[sf].sym == s) 307 break; 308 s->sym = sym; 309 zname(&outbuf, s, t); 310 h[sym].sym = s; 311 h[sym].type = t; 312 sf = sym; 313 sym++; 314 if(sym >= NSYM) 315 sym = 1; 316 break; 317 } 318 st = 0; 319 s = p->to.sym; 320 while(s != S) { 321 st = s->sym; 322 if(st < 0 || st >= NSYM) 323 st = 0; 324 t = p->to.name; 325 if(h[st].type == t) 326 if(h[st].sym == s) 327 break; 328 s->sym = sym; 329 zname(&outbuf, s, t); 330 h[sym].sym = s; 331 h[sym].type = t; 332 st = sym; 333 sym++; 334 if(sym >= NSYM) 335 sym = 1; 336 if(st == sf) 337 goto jackpot; 338 break; 339 } 340 zwrite(&outbuf, p, sf, st); 341 } 342 firstp = P; 343 lastp = P; 344 } 345 346 void 347 zwrite(Biobuf *b, Prog *p, int sf, int st) 348 { 349 char bf[100], *bp; 350 long l; 351 352 bf[0] = p->as; 353 bf[1] = p->as>>8; 354 bf[2] = p->reg; 355 if(p->from3.type != D_NONE) 356 bf[2] |= 0x40; 357 l = p->lineno; 358 bf[3] = l; 359 bf[4] = l>>8; 360 bf[5] = l>>16; 361 bf[6] = l>>24; 362 bp = zaddr(bf+7, &p->from, sf); 363 if(bf[2] & 0x40) 364 bp = zaddr(bp, &p->from3, 0); 365 bp = zaddr(bp, &p->to, st); 366 Bwrite(b, bf, bp-bf); 367 } 368 369 void 370 outhist(Biobuf *b) 371 { 372 Hist *h; 373 char *p, *q, *op, c; 374 Prog pg; 375 int n; 376 377 pg = zprog; 378 pg.as = AHISTORY; 379 c = pathchar(); 380 for(h = hist; h != H; h = h->link) { 381 p = h->name; 382 op = 0; 383 /* on windows skip drive specifier in pathname */ 384 if(systemtype(Windows) && p && p[1] == ':'){ 385 p += 2; 386 c = *p; 387 } 388 if(p && p[0] != c && h->offset == 0 && pathname){ 389 /* on windows skip drive specifier in pathname */ 390 if(systemtype(Windows) && pathname[1] == ':') { 391 op = p; 392 p = pathname+2; 393 c = *p; 394 } else if(pathname[0] == c){ 395 op = p; 396 p = pathname; 397 } 398 } 399 while(p) { 400 q = utfrune(p, c); 401 if(q) { 402 n = q-p; 403 if(n == 0){ 404 n = 1; /* leading "/" */ 405 *p = '/'; /* don't emit "\" on windows */ 406 } 407 q++; 408 } else { 409 n = strlen(p); 410 q = 0; 411 } 412 if(n) { 413 Bputc(b, ANAME); 414 Bputc(b, ANAME>>8); 415 Bputc(b, D_FILE); 416 Bputc(b, 1); 417 Bputc(b, '<'); 418 Bwrite(b, p, n); 419 Bputc(b, 0); 420 } 421 p = q; 422 if(p == 0 && op) { 423 p = op; 424 op = 0; 425 } 426 } 427 pg.lineno = h->line; 428 pg.to.type = zprog.to.type; 429 pg.to.offset = h->offset; 430 if(h->offset) 431 pg.to.type = D_CONST; 432 433 zwrite(b, &pg, 0, 0); 434 } 435 } 436 437 void 438 zname(Biobuf *b, Sym *s, int t) 439 { 440 char *n, bf[8]; 441 ulong sig; 442 443 n = s->name; 444 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ 445 sig = sign(s); 446 bf[0] = ASIGNAME; 447 bf[1] = ASIGNAME>>8; 448 bf[2] = sig; 449 bf[3] = sig>>8; 450 bf[4] = sig>>16; 451 bf[5] = sig>>24; 452 bf[6] = t; 453 bf[7] = s->sym; 454 Bwrite(b, bf, 8); 455 s->sig = SIGDONE; 456 } 457 else{ 458 bf[0] = ANAME; 459 bf[1] = ANAME>>8; 460 bf[2] = t; /* type */ 461 bf[3] = s->sym; /* sym */ 462 Bwrite(b, bf, 4); 463 } 464 Bwrite(b, n, strlen(n)+1); 465 } 466 467 char* 468 zaddr(char *bp, Adr *a, int s) 469 { 470 long l; 471 Ieee e; 472 473 bp[0] = a->type; 474 bp[1] = a->reg; 475 bp[2] = s; 476 bp[3] = a->name; 477 bp += 4; 478 switch(a->type) { 479 default: 480 diag(Z, "unknown type %d in zaddr", a->type); 481 482 case D_NONE: 483 case D_REG: 484 case D_FREG: 485 case D_CREG: 486 break; 487 488 case D_OREG: 489 case D_CONST: 490 case D_BRANCH: 491 l = a->offset; 492 bp[0] = l; 493 bp[1] = l>>8; 494 bp[2] = l>>16; 495 bp[3] = l>>24; 496 bp += 4; 497 break; 498 499 case D_SCONST: 500 memmove(bp, a->sval, NSNAME); 501 bp += NSNAME; 502 break; 503 504 case D_FCONST: 505 ieeedtod(&e, a->dval); 506 l = e.l; 507 bp[0] = l; 508 bp[1] = l>>8; 509 bp[2] = l>>16; 510 bp[3] = l>>24; 511 bp += 4; 512 l = e.h; 513 bp[0] = l; 514 bp[1] = l>>8; 515 bp[2] = l>>16; 516 bp[3] = l>>24; 517 bp += 4; 518 break; 519 } 520 return bp; 521 } 522 523 static int 524 doubled(Type *t) 525 { 526 Type *v; 527 528 if(debug['4']) 529 return 0; 530 if(t->nbits != 0) 531 return 0; 532 switch(t->etype){ 533 case TDOUBLE: 534 return 1; 535 536 case TARRAY: 537 for(v=t; v->etype==TARRAY; v=v->link) 538 ; 539 return v->etype == TDOUBLE; 540 541 case TSTRUCT: 542 case TUNION: 543 for(v = t->link; v != T; v = v->down) 544 if(doubled(v)) 545 return 1; 546 break; 547 } 548 return 0; 549 } 550 551 long 552 align(long i, Type *t, int op) 553 { 554 long o; 555 Type *v; 556 int w, pc; 557 558 o = i; 559 w = 1; 560 pc = 0; 561 switch(op) { 562 default: 563 diag(Z, "unknown align opcode %d", op); 564 break; 565 566 case Asu2: /* padding at end of a struct */ 567 w = doubled(t)? SZ_DOUBLE: SZ_LONG; 568 if(packflg) 569 w = packflg; 570 break; 571 572 case Ael1: /* initial align of struct element (also automatic) */ 573 for(v=t; v->etype==TARRAY; v=v->link) 574 ; 575 w = ewidth[v->etype]; 576 if(w <= 0 || w >= SZ_LONG){ 577 if(doubled(v)){ 578 w = SZ_DOUBLE; 579 doubleflag = 1; 580 }else 581 w = SZ_LONG; 582 } 583 if(packflg) 584 w = packflg; 585 break; 586 587 case Ael2: /* width of a struct element */ 588 o += t->width; 589 break; 590 591 case Aarg0: /* initial passbyptr argument in arg list */ 592 if(typesuv[t->etype]) { 593 o = align(o, types[TIND], Aarg1); 594 o = align(o, types[TIND], Aarg2); 595 } 596 break; 597 598 case Aarg1: /* initial align of parameter */ 599 w = ewidth[t->etype]; 600 if(w <= 0 || w >= SZ_LONG) { 601 if(doubled(t)){ 602 w = SZ_DOUBLE; 603 pc = SZ_LONG; /* alignment must account for pc */ 604 hasdoubled = 1; 605 }else 606 w = SZ_LONG; 607 break; 608 } 609 o += SZ_LONG - w; /* big endian adjustment */ 610 w = 1; 611 break; 612 613 case Aarg2: /* width of a parameter */ 614 o += t->width; 615 w = SZ_LONG; 616 if(doubled(t)){ 617 pc = SZ_LONG; 618 hasdoubled = 1; 619 } 620 break; 621 622 case Aaut3: /* total align of automatic */ 623 doubleflag = 0; 624 o = align(o, t, Ael1); 625 o = align(o, t, Ael2); 626 hasdoubled |= doubleflag; 627 break; 628 } 629 o = round(o+pc, w)-pc; 630 if(debug['A']) 631 print("align %s %ld %T = %ld\n", bnames[op], i, t, o); 632 return o; 633 } 634 635 long 636 maxround(long max, long v) 637 { 638 int w; 639 640 w = SZ_LONG; 641 if((debug['8'] || hasdoubled) && !debug['4']) 642 w = SZ_DOUBLE; 643 v = round(v, w); 644 if(v > max) 645 return v; 646 return max; 647 } 648