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