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