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