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['K']) 13 print("case = %.8llux\n", q->val); 14 gcmp(OEQ, n, 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['K']) 25 print("case > %.8llux\n", r->val); 26 gcmp(OGT, n, 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['K']) 34 print("case < %.8llux\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, tfield, nodconst(v), n1); 65 } else { 66 sh = 32 - b->type->shift - b->type->nbits; 67 if(sh > 0) 68 gopcode(OASHL, tfield, nodconst(sh), n1); 69 sh += b->type->shift; 70 if(sh > 0) 71 if(typeu[b->type->etype]) 72 gopcode(OLSHR, tfield, nodconst(sh), n1); 73 else 74 gopcode(OASHR, tfield, 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 gextern(Sym *s, Node *a, long o, long w) 132 { 133 if(0 && a->op == OCONST && typev[a->type->etype]) { 134 gpseudo(ADATA, s, lo64(a)); 135 p->from.offset += o; 136 p->from.scale = 4; 137 gpseudo(ADATA, s, hi64(a)); 138 p->from.offset += o + 4; 139 p->from.scale = 4; 140 return; 141 } 142 gpseudo(ADATA, s, a); 143 p->from.offset += o; 144 p->from.scale = w; 145 switch(p->to.type) { 146 default: 147 p->to.index = p->to.type; 148 p->to.type = D_ADDR; 149 case D_CONST: 150 case D_FCONST: 151 case D_ADDR: 152 break; 153 } 154 } 155 156 void zname(Biobuf*, Sym*, int); 157 void zaddr(Biobuf*, Adr*, int); 158 void outhist(Biobuf*); 159 160 void 161 outcode(void) 162 { 163 struct { Sym *sym; short type; } h[NSYM]; 164 Prog *p; 165 Sym *s; 166 int f, sf, st, t, sym; 167 Biobuf b; 168 169 if(debug['S']) { 170 for(p = firstp; p != P; p = p->link) 171 if(p->as != ADATA && p->as != AGLOBL) 172 pc--; 173 for(p = firstp; p != P; p = p->link) { 174 print("%P\n", p); 175 if(p->as != ADATA && p->as != AGLOBL) 176 pc++; 177 } 178 } 179 f = open(outfile, OWRITE); 180 if(f < 0) { 181 diag(Z, "cannot open %s", outfile); 182 return; 183 } 184 Binit(&b, f, OWRITE); 185 Bseek(&b, 0L, 2); 186 outhist(&b); 187 for(sym=0; sym<NSYM; sym++) { 188 h[sym].sym = S; 189 h[sym].type = 0; 190 } 191 sym = 1; 192 for(p = firstp; p != P; p = p->link) { 193 jackpot: 194 sf = 0; 195 s = p->from.sym; 196 while(s != S) { 197 sf = s->sym; 198 if(sf < 0 || sf >= NSYM) 199 sf = 0; 200 t = p->from.type; 201 if(t == D_ADDR) 202 t = p->from.index; 203 if(h[sf].type == t) 204 if(h[sf].sym == s) 205 break; 206 s->sym = sym; 207 zname(&b, s, t); 208 h[sym].sym = s; 209 h[sym].type = t; 210 sf = sym; 211 sym++; 212 if(sym >= NSYM) 213 sym = 1; 214 break; 215 } 216 st = 0; 217 s = p->to.sym; 218 while(s != S) { 219 st = s->sym; 220 if(st < 0 || st >= NSYM) 221 st = 0; 222 t = p->to.type; 223 if(t == D_ADDR) 224 t = p->to.index; 225 if(h[st].type == t) 226 if(h[st].sym == s) 227 break; 228 s->sym = sym; 229 zname(&b, s, t); 230 h[sym].sym = s; 231 h[sym].type = t; 232 st = sym; 233 sym++; 234 if(sym >= NSYM) 235 sym = 1; 236 if(st == sf) 237 goto jackpot; 238 break; 239 } 240 Bputc(&b, p->as); 241 Bputc(&b, p->as>>8); 242 Bputc(&b, p->lineno); 243 Bputc(&b, p->lineno>>8); 244 Bputc(&b, p->lineno>>16); 245 Bputc(&b, p->lineno>>24); 246 zaddr(&b, &p->from, sf); 247 zaddr(&b, &p->to, st); 248 } 249 Bflush(&b); 250 close(f); 251 firstp = P; 252 lastp = P; 253 } 254 255 void 256 outhist(Biobuf *b) 257 { 258 Hist *h; 259 char *p, *q, *op, c; 260 Prog pg; 261 int n; 262 263 pg = zprog; 264 pg.as = AHISTORY; 265 c = pathchar(); 266 for(h = hist; h != H; h = h->link) { 267 p = h->name; 268 op = 0; 269 /* on windows skip drive specifier in pathname */ 270 if(systemtype(Windows) && p && p[1] == ':'){ 271 p += 2; 272 c = *p; 273 } 274 if(p && p[0] != c && h->offset == 0 && pathname){ 275 /* on windows skip drive specifier in pathname */ 276 if(systemtype(Windows) && pathname[1] == ':') { 277 op = p; 278 p = pathname+2; 279 c = *p; 280 } else if(pathname[0] == c){ 281 op = p; 282 p = pathname; 283 } 284 } 285 while(p) { 286 q = utfrune(p, c); 287 if(q) { 288 n = q-p; 289 if(n == 0){ 290 n = 1; /* leading "/" */ 291 *p = '/'; /* don't emit "\" on windows */ 292 } 293 q++; 294 } else { 295 n = strlen(p); 296 q = 0; 297 } 298 if(n) { 299 Bputc(b, ANAME); 300 Bputc(b, ANAME>>8); 301 Bputc(b, D_FILE); 302 Bputc(b, 1); 303 Bputc(b, '<'); 304 Bwrite(b, p, n); 305 Bputc(b, 0); 306 } 307 p = q; 308 if(p == 0 && op) { 309 p = op; 310 op = 0; 311 } 312 } 313 pg.lineno = h->line; 314 pg.to.type = zprog.to.type; 315 pg.to.offset = h->offset; 316 if(h->offset) 317 pg.to.type = D_CONST; 318 319 Bputc(b, pg.as); 320 Bputc(b, pg.as>>8); 321 Bputc(b, pg.lineno); 322 Bputc(b, pg.lineno>>8); 323 Bputc(b, pg.lineno>>16); 324 Bputc(b, pg.lineno>>24); 325 zaddr(b, &pg.from, 0); 326 zaddr(b, &pg.to, 0); 327 } 328 } 329 330 void 331 zname(Biobuf *b, Sym *s, int t) 332 { 333 char *n; 334 ulong sig; 335 336 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ 337 sig = sign(s); 338 Bputc(b, ASIGNAME); 339 Bputc(b, ASIGNAME>>8); 340 Bputc(b, sig); 341 Bputc(b, sig>>8); 342 Bputc(b, sig>>16); 343 Bputc(b, sig>>24); 344 s->sig = SIGDONE; 345 } 346 else{ 347 Bputc(b, ANAME); /* as */ 348 Bputc(b, ANAME>>8); /* as */ 349 } 350 Bputc(b, t); /* type */ 351 Bputc(b, s->sym); /* sym */ 352 n = s->name; 353 while(*n) { 354 Bputc(b, *n); 355 n++; 356 } 357 Bputc(b, 0); 358 } 359 360 void 361 zaddr(Biobuf *b, Adr *a, int s) 362 { 363 long l; 364 int i, t; 365 char *n; 366 Ieee e; 367 368 t = 0; 369 if(a->index != D_NONE || a->scale != 0) 370 t |= T_INDEX; 371 if(s != 0) 372 t |= T_SYM; 373 374 switch(a->type) { 375 default: 376 t |= T_TYPE; 377 case D_NONE: 378 if(a->offset != 0) { 379 t |= T_OFFSET; 380 l = a->offset; 381 if((vlong)l != a->offset) 382 t |= T_64; 383 } 384 break; 385 case D_FCONST: 386 t |= T_FCONST; 387 break; 388 case D_SCONST: 389 t |= T_SCONST; 390 break; 391 } 392 Bputc(b, t); 393 394 if(t & T_INDEX) { /* implies index, scale */ 395 Bputc(b, a->index); 396 Bputc(b, a->scale); 397 } 398 if(t & T_OFFSET) { /* implies offset */ 399 l = a->offset; 400 Bputc(b, l); 401 Bputc(b, l>>8); 402 Bputc(b, l>>16); 403 Bputc(b, l>>24); 404 if(t & T_64) { 405 l = a->offset>>32; 406 Bputc(b, l); 407 Bputc(b, l>>8); 408 Bputc(b, l>>16); 409 Bputc(b, l>>24); 410 } 411 } 412 if(t & T_SYM) /* implies sym */ 413 Bputc(b, s); 414 if(t & T_FCONST) { 415 ieeedtod(&e, a->dval); 416 l = e.l; 417 Bputc(b, l); 418 Bputc(b, l>>8); 419 Bputc(b, l>>16); 420 Bputc(b, l>>24); 421 l = e.h; 422 Bputc(b, l); 423 Bputc(b, l>>8); 424 Bputc(b, l>>16); 425 Bputc(b, l>>24); 426 return; 427 } 428 if(t & T_SCONST) { 429 n = a->sval; 430 for(i=0; i<NSNAME; i++) { 431 Bputc(b, *n); 432 n++; 433 } 434 return; 435 } 436 if(t & T_TYPE) 437 Bputc(b, a->type); 438 } 439 440 long 441 align(long i, Type *t, int op) 442 { 443 long o; 444 Type *v; 445 int w; 446 447 o = i; 448 w = 1; 449 switch(op) { 450 default: 451 diag(Z, "unknown align opcode %d", op); 452 break; 453 454 case Asu2: /* padding at end of a struct */ 455 w = SZ_VLONG; 456 if(packflg) 457 w = packflg; 458 break; 459 460 case Ael1: /* initial align of struct element */ 461 for(v=t; v->etype==TARRAY; v=v->link) 462 ; 463 w = ewidth[v->etype]; 464 if(w <= 0 || w >= SZ_VLONG) 465 w = SZ_VLONG; 466 if(packflg) 467 w = packflg; 468 break; 469 470 case Ael2: /* width of a struct element */ 471 o += t->width; 472 break; 473 474 case Aarg0: /* initial passbyptr argument in arg list */ 475 if(typesu[t->etype]) { 476 o = align(o, types[TIND], Aarg1); 477 o = align(o, types[TIND], Aarg2); 478 } 479 break; 480 481 case Aarg1: /* initial align of parameter */ 482 w = ewidth[t->etype]; 483 if(w <= 0 || w >= SZ_VLONG) { 484 w = SZ_VLONG; 485 break; 486 } 487 w = 1; /* little endian no adjustment */ 488 break; 489 490 case Aarg2: /* width of a parameter */ 491 o += t->width; 492 w = SZ_VLONG; 493 break; 494 495 case Aaut3: /* total allign of automatic */ 496 o = align(o, t, Ael1); 497 o = align(o, t, Ael2); 498 break; 499 } 500 o = round(o, w); 501 if(debug['A']) 502 print("align %s %ld %T = %ld\n", bnames[op], i, t, o); 503 return o; 504 } 505 506 long 507 maxround(long max, long v) 508 { 509 v = round(v, SZ_VLONG); 510 if(v > max) 511 return v; 512 return max; 513 } 514