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