1 #include "gc.h" 2 3 int 4 swcmp(void *a1, void *a2) 5 { 6 C1 *p1, *p2; 7 8 p1 = a1; 9 p2 = a2; 10 if(p1->val < p2->val) 11 return -1; 12 return p1->val > p2->val; 13 } 14 15 void 16 doswit(Node *n) 17 { 18 Case *c; 19 C1 *q, *iq; 20 long def, nc, i; 21 22 def = 0; 23 nc = 0; 24 for(c = cases; c->link != C; c = c->link) { 25 if(c->def) { 26 if(def) 27 diag(n, "more than one default in switch"); 28 def = c->label; 29 continue; 30 } 31 nc++; 32 } 33 34 i = nc*sizeof(C1); 35 while(nhunk < i) 36 gethunk(); 37 iq = (C1*)hunk; 38 nhunk -= i; 39 hunk += i; 40 41 q = iq; 42 for(c = cases; c->link != C; c = c->link) { 43 if(c->def) 44 continue; 45 q->label = c->label; 46 q->val = c->val; 47 q++; 48 } 49 qsort(iq, nc, sizeof(C1), swcmp); 50 if(debug['W']) 51 for(i=0; i<nc; i++) 52 print("case %2d: = %.8lux\n", i, iq[i].val); 53 if(def == 0) 54 def = breakpc; 55 for(i=0; i<nc-1; i++) 56 if(iq[i].val == iq[i+1].val) 57 diag(n, "duplicate cases in switch %ld", iq[i].val); 58 swit1(iq, nc, def, n); 59 } 60 61 void 62 swit1(C1 *q, int nc, long def, Node *n) 63 { 64 C1 *r; 65 int i; 66 Prog *sp; 67 68 if(nc < 5) { 69 for(i=0; i<nc; i++) { 70 if(debug['W']) 71 print("case = %.8lux\n", q->val); 72 gopcode(OEQ, n->type, n, nodconst(q->val)); 73 patch(p, q->label); 74 q++; 75 } 76 gbranch(OGOTO); 77 patch(p, def); 78 return; 79 } 80 i = nc / 2; 81 r = q+i; 82 if(debug['W']) 83 print("case > %.8lux\n", r->val); 84 gopcode(OGT, n->type, n, nodconst(r->val)); 85 sp = p; 86 gbranch(OGOTO); 87 p->as = AJEQ; 88 patch(p, r->label); 89 swit1(q, i, def, n); 90 91 if(debug['W']) 92 print("case < %.8lux\n", r->val); 93 patch(sp, pc); 94 swit1(r+1, nc-i-1, def, n); 95 } 96 97 void 98 cas(void) 99 { 100 Case *c; 101 102 ALLOC(c, Case); 103 c->link = cases; 104 cases = c; 105 } 106 107 void 108 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 109 { 110 int sh; 111 long v; 112 Node *l; 113 114 /* 115 * n1 gets adjusted/masked value 116 * n2 gets address of cell 117 * n3 gets contents of cell 118 */ 119 l = b->left; 120 if(n2 != Z) { 121 regalloc(n1, l, nn); 122 reglcgen(n2, l, Z); 123 regalloc(n3, l, Z); 124 gmove(n2, n3); 125 gmove(n3, n1); 126 } else { 127 regalloc(n1, l, nn); 128 cgen(l, n1); 129 } 130 if(b->type->shift == 0 && typeu[b->type->etype]) { 131 v = ~0 + (1L << b->type->nbits); 132 gopcode(OAND, types[TLONG], nodconst(v), n1); 133 } else { 134 sh = 32 - b->type->shift - b->type->nbits; 135 if(sh > 0) 136 gopcode(OASHL, types[TLONG], nodconst(sh), n1); 137 sh += b->type->shift; 138 if(sh > 0) 139 if(typeu[b->type->etype]) 140 gopcode(OLSHR, types[TLONG], nodconst(sh), n1); 141 else 142 gopcode(OASHR, types[TLONG], nodconst(sh), n1); 143 } 144 } 145 146 void 147 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 148 { 149 long v; 150 Node nod; 151 int sh; 152 153 regalloc(&nod, b->left, Z); 154 v = ~0 + (1L << b->type->nbits); 155 gopcode(OAND, types[TLONG], nodconst(v), n1); 156 gmove(n1, &nod); 157 if(nn != Z) 158 gmove(n1, nn); 159 sh = b->type->shift; 160 if(sh > 0) 161 gopcode(OASHL, types[TLONG], nodconst(sh), &nod); 162 v <<= sh; 163 gopcode(OAND, types[TLONG], nodconst(~v), n3); 164 gopcode(OOR, types[TLONG], n3, &nod); 165 gmove(&nod, n2); 166 167 regfree(&nod); 168 regfree(n1); 169 regfree(n2); 170 regfree(n3); 171 } 172 173 long 174 outstring(char *s, long n) 175 { 176 long r; 177 178 r = nstring; 179 while(n) { 180 string[mnstring] = *s++; 181 mnstring++; 182 nstring++; 183 if(mnstring >= NSNAME) { 184 gpseudo(ADATA, symstring, nodconst(0L)); 185 p->from.offset += nstring - NSNAME; 186 p->from.scale = NSNAME; 187 p->to.type = D_SCONST; 188 memmove(p->to.sval, string, NSNAME); 189 mnstring = 0; 190 } 191 n--; 192 } 193 return r; 194 } 195 196 long 197 outlstring(ushort *s, long n) 198 { 199 char buf[2]; 200 int c; 201 long r; 202 203 while(nstring & 1) 204 outstring("", 1); 205 r = nstring; 206 while(n > 0) { 207 c = *s++; 208 if(endian(0)) { 209 buf[0] = c>>8; 210 buf[1] = c; 211 } else { 212 buf[0] = c; 213 buf[1] = c>>8; 214 } 215 outstring(buf, 2); 216 n -= sizeof(ushort); 217 } 218 return r; 219 } 220 221 int 222 vlog(Node *n) 223 { 224 225 int s, i; 226 ulong m, v; 227 228 if(n->op != OCONST) 229 goto bad; 230 if(!typechlp[n->type->etype]) 231 goto bad; 232 233 v = n->vconst; 234 235 s = 0; 236 m = MASK(64); 237 for(i=32; i; i>>=1) { 238 m >>= i; 239 if(!(v & m)) { 240 v >>= i; 241 s += i; 242 } 243 } 244 if(v == 1) 245 return s; 246 247 bad: 248 return -1; 249 } 250 251 void 252 nullwarn(Node *l, Node *r) 253 { 254 warn(Z, "result of operation not used"); 255 if(l != Z) 256 cgen(l, Z); 257 if(r != Z) 258 cgen(r, Z); 259 } 260 261 void 262 sextern(Sym *s, Node *a, long o, long w) 263 { 264 long e, lw; 265 266 for(e=0; e<w; e+=NSNAME) { 267 lw = NSNAME; 268 if(w-e < lw) 269 lw = w-e; 270 gpseudo(ADATA, s, nodconst(0L)); 271 p->from.offset += o+e; 272 p->from.scale = lw; 273 p->to.type = D_SCONST; 274 memmove(p->to.sval, a->cstring+e, lw); 275 } 276 } 277 278 void 279 gextern(Sym *s, Node *a, long o, long w) 280 { 281 if(a->op == OCONST && typev[a->type->etype]) { 282 gpseudo(ADATA, s, nodconst((long)(a->vconst>>32))); 283 p->from.offset += o; 284 p->from.scale = 4; 285 gpseudo(ADATA, s, nodconst((long)(a->vconst))); 286 p->from.offset += o + 4; 287 p->from.scale = 4; 288 return; 289 } 290 gpseudo(ADATA, s, a); 291 p->from.offset += o; 292 p->from.scale = w; 293 switch(p->to.type) { 294 default: 295 p->to.index = p->to.type; 296 p->to.type = D_ADDR; 297 case D_CONST: 298 case D_FCONST: 299 case D_ADDR: 300 break; 301 } 302 } 303 304 void zname(Biobuf*, char*, int, int); 305 void zaddr(Biobuf*, Adr*, int); 306 void outhist(Biobuf*); 307 308 void 309 outcode(void) 310 { 311 struct { Sym *sym; short type; } h[NSYM]; 312 Prog *p; 313 Sym *s; 314 int f, sf, st, t, sym; 315 Biobuf b; 316 317 if(debug['S']) { 318 for(p = firstp; p != P; p = p->link) 319 if(p->as != ADATA && p->as != AGLOBL) 320 pc--; 321 for(p = firstp; p != P; p = p->link) { 322 print("%P\n", p); 323 if(p->as != ADATA && p->as != AGLOBL) 324 pc++; 325 } 326 } 327 f = open(outfile, OWRITE); 328 if(f < 0) { 329 diag(Z, "cannot open %s", outfile); 330 return; 331 } 332 Binit(&b, f, OWRITE); 333 Bseek(&b, 0L, 2); 334 outhist(&b); 335 for(sym=0; sym<NSYM; sym++) { 336 h[sym].sym = S; 337 h[sym].type = 0; 338 } 339 sym = 1; 340 for(p = firstp; p != P; p = p->link) { 341 jackpot: 342 sf = 0; 343 s = p->from.sym; 344 while(s != S) { 345 sf = s->sym; 346 if(sf < 0 || sf >= NSYM) 347 sf = 0; 348 t = p->from.type; 349 if(t == D_ADDR) 350 t = p->from.index; 351 if(h[sf].type == t) 352 if(h[sf].sym == s) 353 break; 354 zname(&b, s->name, t, sym); 355 s->sym = sym; 356 h[sym].sym = s; 357 h[sym].type = t; 358 sf = sym; 359 sym++; 360 if(sym >= NSYM) 361 sym = 1; 362 break; 363 } 364 st = 0; 365 s = p->to.sym; 366 while(s != S) { 367 st = s->sym; 368 if(st < 0 || st >= NSYM) 369 st = 0; 370 t = p->to.type; 371 if(t == D_ADDR) 372 t = p->to.index; 373 if(h[st].type == t) 374 if(h[st].sym == s) 375 break; 376 zname(&b, s->name, t, sym); 377 s->sym = sym; 378 h[sym].sym = s; 379 h[sym].type = t; 380 st = sym; 381 sym++; 382 if(sym >= NSYM) 383 sym = 1; 384 if(st == sf) 385 goto jackpot; 386 break; 387 } 388 Bputc(&b, p->as); 389 Bputc(&b, p->as>>8); 390 Bputc(&b, p->lineno); 391 Bputc(&b, p->lineno>>8); 392 Bputc(&b, p->lineno>>16); 393 Bputc(&b, p->lineno>>24); 394 zaddr(&b, &p->from, sf); 395 zaddr(&b, &p->to, st); 396 } 397 Bflush(&b); 398 close(f); 399 firstp = P; 400 lastp = P; 401 } 402 403 404 405 void 406 outhist(Biobuf *b) 407 { 408 Hist *h; 409 char *p, *q, *op; 410 Prog pg; 411 int n; 412 413 pg = zprog; 414 pg.as = AHISTORY; 415 for(h = hist; h != H; h = h->link) { 416 p = h->name; 417 op = 0; 418 if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') { 419 op = p; 420 p = pathname; 421 } 422 while(p) { 423 q = utfrune(p, '/'); 424 if(q) { 425 n = q-p; 426 if(n == 0) 427 n = 1; /* leading "/" */ 428 q++; 429 } else { 430 n = strlen(p); 431 q = 0; 432 } 433 if(n) { 434 Bputc(b, ANAME); 435 Bputc(b, ANAME>>8); 436 Bputc(b, D_FILE); 437 Bputc(b, 1); 438 Bputc(b, '<'); 439 Bwrite(b, p, n); 440 Bputc(b, 0); 441 } 442 p = q; 443 if(p == 0 && op) { 444 p = op; 445 op = 0; 446 } 447 } 448 pg.lineno = h->line; 449 pg.to.type = zprog.to.type; 450 pg.to.offset = h->offset; 451 if(h->offset) 452 pg.to.type = D_CONST; 453 454 Bputc(b, pg.as); 455 Bputc(b, pg.as>>8); 456 Bputc(b, pg.lineno); 457 Bputc(b, pg.lineno>>8); 458 Bputc(b, pg.lineno>>16); 459 Bputc(b, pg.lineno>>24); 460 zaddr(b, &pg.from, 0); 461 zaddr(b, &pg.to, 0); 462 } 463 } 464 465 void 466 zname(Biobuf *b, char *n, int t, int s) 467 { 468 469 Bputc(b, ANAME); /* as */ 470 Bputc(b, ANAME>>8); /* as */ 471 Bputc(b, t); /* type */ 472 Bputc(b, s); /* sym */ 473 while(*n) { 474 Bputc(b, *n); 475 n++; 476 } 477 Bputc(b, 0); 478 } 479 480 void 481 zaddr(Biobuf *b, Adr *a, int s) 482 { 483 long l; 484 int i, t; 485 char *n; 486 Ieee e; 487 488 t = 0; 489 if(a->index != D_NONE || a->scale != 0) 490 t |= T_INDEX; 491 if(s != 0) 492 t |= T_SYM; 493 494 switch(a->type) { 495 default: 496 t |= T_TYPE; 497 case D_NONE: 498 if(a->offset != 0) 499 t |= T_OFFSET; 500 break; 501 case D_FCONST: 502 t |= T_FCONST; 503 break; 504 case D_SCONST: 505 t |= T_SCONST; 506 break; 507 } 508 Bputc(b, t); 509 510 if(t & T_INDEX) { /* implies index, scale */ 511 Bputc(b, a->index); 512 Bputc(b, a->scale); 513 } 514 if(t & T_OFFSET) { /* implies offset */ 515 l = a->offset; 516 Bputc(b, l); 517 Bputc(b, l>>8); 518 Bputc(b, l>>16); 519 Bputc(b, l>>24); 520 } 521 if(t & T_SYM) /* implies sym */ 522 Bputc(b, s); 523 if(t & T_FCONST) { 524 ieeedtod(&e, a->dval); 525 l = e.l; 526 Bputc(b, l); 527 Bputc(b, l>>8); 528 Bputc(b, l>>16); 529 Bputc(b, l>>24); 530 l = e.h; 531 Bputc(b, l); 532 Bputc(b, l>>8); 533 Bputc(b, l>>16); 534 Bputc(b, l>>24); 535 return; 536 } 537 if(t & T_SCONST) { 538 n = a->sval; 539 for(i=0; i<NSNAME; i++) { 540 Bputc(b, *n); 541 n++; 542 } 543 return; 544 } 545 if(t & T_TYPE) 546 Bputc(b, a->type); 547 } 548 549 void 550 ieeedtod(Ieee *ieee, double native) 551 { 552 double fr, ho, f; 553 int exp; 554 555 if(native < 0) { 556 ieeedtod(ieee, -native); 557 ieee->h |= 0x80000000L; 558 return; 559 } 560 if(native == 0) { 561 ieee->l = 0; 562 ieee->h = 0; 563 return; 564 } 565 fr = frexp(native, &exp); 566 f = 2097152L; /* shouldnt use fp constants here */ 567 fr = modf(fr*f, &ho); 568 ieee->h = ho; 569 ieee->h &= 0xfffffL; 570 ieee->h |= (exp+1022L) << 20; 571 f = 65536L; 572 fr = modf(fr*f, &ho); 573 ieee->l = ho; 574 ieee->l <<= 16; 575 ieee->l |= (long)(fr*f); 576 } 577 578 char* xonames[] = 579 { 580 "INDEX", 581 "XEND", 582 }; 583 584 char* 585 xOconv(int a) 586 { 587 if(a <= OEND || a > OXEND) 588 return "**badO**"; 589 return xonames[a-OEND-1]; 590 } 591 592 int 593 endian(int w) 594 { 595 596 USED(w); 597 return 0; 598 } 599 600 int 601 passbypointer(int et) 602 { 603 604 return typesuv[et]; 605 } 606 607 int 608 argalign(long typewidth, long offset, int offsp) 609 { 610 USED(typewidth,offset,offsp); 611 return 0; 612 } 613