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