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 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['K']) 25 print("case > %.8llux\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['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, 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 gextern(Sym *s, Node *a, long o, long w) 132 { 133 if(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 break; 381 case D_FCONST: 382 t |= T_FCONST; 383 break; 384 case D_SCONST: 385 t |= T_SCONST; 386 break; 387 } 388 Bputc(b, t); 389 390 if(t & T_INDEX) { /* implies index, scale */ 391 Bputc(b, a->index); 392 Bputc(b, a->scale); 393 } 394 if(t & T_OFFSET) { /* implies offset */ 395 l = a->offset; 396 Bputc(b, l); 397 Bputc(b, l>>8); 398 Bputc(b, l>>16); 399 Bputc(b, l>>24); 400 } 401 if(t & T_SYM) /* implies sym */ 402 Bputc(b, s); 403 if(t & T_FCONST) { 404 ieeedtod(&e, a->dval); 405 l = e.l; 406 Bputc(b, l); 407 Bputc(b, l>>8); 408 Bputc(b, l>>16); 409 Bputc(b, l>>24); 410 l = e.h; 411 Bputc(b, l); 412 Bputc(b, l>>8); 413 Bputc(b, l>>16); 414 Bputc(b, l>>24); 415 return; 416 } 417 if(t & T_SCONST) { 418 n = a->sval; 419 for(i=0; i<NSNAME; i++) { 420 Bputc(b, *n); 421 n++; 422 } 423 return; 424 } 425 if(t & T_TYPE) 426 Bputc(b, a->type); 427 } 428 429 long 430 align(long i, Type *t, int op) 431 { 432 long o; 433 Type *v; 434 int w; 435 436 o = i; 437 w = 1; 438 switch(op) { 439 default: 440 diag(Z, "unknown align opcode %d", op); 441 break; 442 443 case Asu2: /* padding at end of a struct */ 444 w = SZ_LONG; 445 if(packflg) 446 w = packflg; 447 break; 448 449 case Ael1: /* initial allign of struct element */ 450 for(v=t; v->etype==TARRAY; v=v->link) 451 ; 452 w = ewidth[v->etype]; 453 if(w <= 0 || w >= SZ_LONG) 454 w = SZ_LONG; 455 if(packflg) 456 w = packflg; 457 break; 458 459 case Ael2: /* width of a struct element */ 460 o += t->width; 461 break; 462 463 case Aarg0: /* initial passbyptr argument in arg list */ 464 if(typesuv[t->etype]) { 465 o = align(o, types[TIND], Aarg1); 466 o = align(o, types[TIND], Aarg2); 467 } 468 break; 469 470 case Aarg1: /* initial allign of parameter */ 471 w = ewidth[t->etype]; 472 if(w <= 0 || w >= SZ_LONG) { 473 w = SZ_LONG; 474 break; 475 } 476 w = 1; /* little endian no adjustment */ 477 break; 478 479 case Aarg2: /* width of a parameter */ 480 o += t->width; 481 w = SZ_LONG; 482 break; 483 484 case Aaut3: /* total allign of automatic */ 485 o = align(o, t, Ael1); 486 o = align(o, t, Ael2); 487 break; 488 } 489 o = round(o, w); 490 if(debug['A']) 491 print("align %s %ld %T = %ld\n", bnames[op], i, t, o); 492 return o; 493 } 494 495 long 496 maxround(long max, long v) 497 { 498 v = round(v, SZ_LONG); 499 if(v > max) 500 return v; 501 return max; 502 } 503