github.com/hongwozai/go-src-1.4.3@v0.0.0-20191127132709-dc3fce3dbccb/src/cmd/5c/swt.c (about) 1 // Inferno utils/5c/swt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/swt.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #include "gc.h" 32 33 void 34 swit1(C1 *q, int nc, int32 def, Node *n) 35 { 36 Node nreg; 37 38 if(typev[n->type->etype]) { 39 regsalloc(&nreg, n); 40 nreg.type = types[TVLONG]; 41 cgen(n, &nreg); 42 swit2(q, nc, def, &nreg); 43 return; 44 } 45 46 regalloc(&nreg, n, Z); 47 nreg.type = types[TLONG]; 48 cgen(n, &nreg); 49 swit2(q, nc, def, &nreg); 50 regfree(&nreg); 51 } 52 53 void 54 swit2(C1 *q, int nc, int32 def, Node *n) 55 { 56 C1 *r; 57 int i; 58 int32 v; 59 Prog *sp; 60 61 if(nc >= 3) { 62 i = (q+nc-1)->val - (q+0)->val; 63 if(!nacl && i > 0 && i < nc*2) 64 goto direct; 65 } 66 if(nc < 5) { 67 for(i=0; i<nc; i++) { 68 if(debug['W']) 69 print("case = %.8ux\n", q->val); 70 gopcode(OEQ, nodconst(q->val), n, Z); 71 patch(p, q->label); 72 q++; 73 } 74 gbranch(OGOTO); 75 patch(p, def); 76 return; 77 } 78 79 i = nc / 2; 80 r = q+i; 81 if(debug['W']) 82 print("case > %.8ux\n", r->val); 83 gopcode(OGT, nodconst(r->val), n, Z); 84 sp = p; 85 gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */ 86 patch(p, r->label); 87 swit2(q, i, def, n); 88 89 if(debug['W']) 90 print("case < %.8ux\n", r->val); 91 patch(sp, pc); 92 swit2(r+1, nc-i-1, def, n); 93 return; 94 95 direct: 96 v = q->val; 97 if(v != 0) 98 gopcode(OSUB, nodconst(v), Z, n); 99 gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z); 100 patch(p, def); 101 for(i=0; i<nc; i++) { 102 if(debug['W']) 103 print("case = %.8ux\n", q->val); 104 while(q->val != v) { 105 nextpc(); 106 p->as = ABCASE; 107 patch(p, def); 108 v++; 109 } 110 nextpc(); 111 p->as = ABCASE; 112 patch(p, q->label); 113 q++; 114 v++; 115 } 116 gbranch(OGOTO); /* so that regopt() won't be confused */ 117 patch(p, def); 118 } 119 120 void 121 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 122 { 123 int sh; 124 int32 v; 125 Node *l; 126 127 /* 128 * n1 gets adjusted/masked value 129 * n2 gets address of cell 130 * n3 gets contents of cell 131 */ 132 l = b->left; 133 if(n2 != Z) { 134 regalloc(n1, l, nn); 135 reglcgen(n2, l, Z); 136 regalloc(n3, l, Z); 137 gopcode(OAS, n2, Z, n3); 138 gopcode(OAS, n3, Z, n1); 139 } else { 140 regalloc(n1, l, nn); 141 cgen(l, n1); 142 } 143 if(b->type->shift == 0 && typeu[b->type->etype]) { 144 v = ~0 + (1L << b->type->nbits); 145 gopcode(OAND, nodconst(v), Z, n1); 146 } else { 147 sh = 32 - b->type->shift - b->type->nbits; 148 if(sh > 0) 149 gopcode(OASHL, nodconst(sh), Z, n1); 150 sh += b->type->shift; 151 if(sh > 0) 152 if(typeu[b->type->etype]) 153 gopcode(OLSHR, nodconst(sh), Z, n1); 154 else 155 gopcode(OASHR, nodconst(sh), Z, n1); 156 } 157 } 158 159 void 160 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 161 { 162 int32 v; 163 Node nod, *l; 164 int sh; 165 166 /* 167 * n1 has adjusted/masked value 168 * n2 has address of cell 169 * n3 has contents of cell 170 */ 171 l = b->left; 172 regalloc(&nod, l, Z); 173 v = ~0 + (1L << b->type->nbits); 174 gopcode(OAND, nodconst(v), Z, n1); 175 gopcode(OAS, n1, Z, &nod); 176 if(nn != Z) 177 gopcode(OAS, n1, Z, nn); 178 sh = b->type->shift; 179 if(sh > 0) 180 gopcode(OASHL, nodconst(sh), Z, &nod); 181 v <<= sh; 182 gopcode(OAND, nodconst(~v), Z, n3); 183 gopcode(OOR, n3, Z, &nod); 184 gopcode(OAS, &nod, Z, n2); 185 186 regfree(&nod); 187 regfree(n1); 188 regfree(n2); 189 regfree(n3); 190 } 191 192 int32 193 outstring(char *s, int32 n) 194 { 195 int32 r; 196 197 if(suppress) 198 return nstring; 199 r = nstring; 200 while(n) { 201 string[mnstring] = *s++; 202 mnstring++; 203 nstring++; 204 if(mnstring >= NSNAME) { 205 gpseudo(ADATA, symstring, nodconst(0L)); 206 p->from.offset += nstring - NSNAME; 207 p->reg = NSNAME; 208 p->to.type = D_SCONST; 209 memmove(p->to.u.sval, string, NSNAME); 210 mnstring = 0; 211 } 212 n--; 213 } 214 return r; 215 } 216 217 int 218 mulcon(Node *n, Node *nn) 219 { 220 Node *l, *r, nod1, nod2; 221 Multab *m; 222 int32 v, vs; 223 int o; 224 char code[sizeof(m->code)+2], *p; 225 226 if(typefd[n->type->etype]) 227 return 0; 228 l = n->left; 229 r = n->right; 230 if(l->op == OCONST) { 231 l = r; 232 r = n->left; 233 } 234 if(r->op != OCONST) 235 return 0; 236 v = convvtox(r->vconst, n->type->etype); 237 if(v != r->vconst) { 238 if(debug['M']) 239 print("%L multiply conv: %lld\n", n->lineno, r->vconst); 240 return 0; 241 } 242 m = mulcon0(v); 243 if(!m) { 244 if(debug['M']) 245 print("%L multiply table: %lld\n", n->lineno, r->vconst); 246 return 0; 247 } 248 if(debug['M'] && debug['v']) 249 print("%L multiply: %d\n", n->lineno, v); 250 251 memmove(code, m->code, sizeof(m->code)); 252 code[sizeof(m->code)] = 0; 253 254 p = code; 255 if(p[1] == 'i') 256 p += 2; 257 regalloc(&nod1, n, nn); 258 cgen(l, &nod1); 259 vs = v; 260 regalloc(&nod2, n, Z); 261 262 loop: 263 switch(*p) { 264 case 0: 265 regfree(&nod2); 266 if(vs < 0) { 267 gopcode(OAS, &nod1, Z, &nod1); 268 gopcode(OSUB, &nod1, nodconst(0), nn); 269 } else 270 gopcode(OAS, &nod1, Z, nn); 271 regfree(&nod1); 272 return 1; 273 case '+': 274 o = OADD; 275 goto addsub; 276 case '-': 277 o = OSUB; 278 addsub: /* number is r,n,l */ 279 v = p[1] - '0'; 280 r = &nod1; 281 if(v&4) 282 r = &nod2; 283 n = &nod1; 284 if(v&2) 285 n = &nod2; 286 l = &nod1; 287 if(v&1) 288 l = &nod2; 289 gopcode(o, l, n, r); 290 break; 291 default: /* op is shiftcount, number is r,l */ 292 v = p[1] - '0'; 293 r = &nod1; 294 if(v&2) 295 r = &nod2; 296 l = &nod1; 297 if(v&1) 298 l = &nod2; 299 v = *p - 'a'; 300 if(v < 0 || v >= 32) { 301 diag(n, "mulcon unknown op: %c%c", p[0], p[1]); 302 break; 303 } 304 gopcode(OASHL, nodconst(v), l, r); 305 break; 306 } 307 p += 2; 308 goto loop; 309 } 310 311 void 312 sextern(Sym *s, Node *a, int32 o, int32 w) 313 { 314 int32 e, lw; 315 316 for(e=0; e<w; e+=NSNAME) { 317 lw = NSNAME; 318 if(w-e < lw) 319 lw = w-e; 320 gpseudo(ADATA, s, nodconst(0)); 321 p->from.offset += o+e; 322 p->reg = lw; 323 p->to.type = D_SCONST; 324 memmove(p->to.u.sval, a->cstring+e, lw); 325 } 326 } 327 328 void 329 gextern(Sym *s, Node *a, int32 o, int32 w) 330 { 331 332 if(a->op == OCONST && typev[a->type->etype]) { 333 if(isbigendian) 334 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 335 else 336 gpseudo(ADATA, s, nod32const(a->vconst)); 337 p->from.offset += o; 338 p->reg = 4; 339 if(isbigendian) 340 gpseudo(ADATA, s, nod32const(a->vconst)); 341 else 342 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 343 p->from.offset += o + 4; 344 p->reg = 4; 345 return; 346 } 347 gpseudo(ADATA, s, a); 348 p->from.offset += o; 349 p->reg = w; 350 if(p->to.type == D_OREG) 351 p->to.type = D_CONST; 352 } 353 354 void 355 outcode(void) 356 { 357 Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion()); 358 if(pragcgobuf.to > pragcgobuf.start) { 359 Bprint(&outbuf, "\n"); 360 Bprint(&outbuf, "$$ // exports\n\n"); 361 Bprint(&outbuf, "$$ // local types\n\n"); 362 Bprint(&outbuf, "$$ // cgo\n"); 363 Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf)); 364 Bprint(&outbuf, "\n$$\n\n"); 365 } 366 Bprint(&outbuf, "!\n"); 367 368 writeobj(ctxt, &outbuf); 369 lastp = P; 370 } 371 372 int32 373 align(int32 i, Type *t, int op, int32 *maxalign) 374 { 375 int32 o; 376 Type *v; 377 int w, packw; 378 379 o = i; 380 w = 1; 381 packw = 0; 382 switch(op) { 383 default: 384 diag(Z, "unknown align opcode %d", op); 385 break; 386 387 case Asu2: /* padding at end of a struct */ 388 w = *maxalign; 389 if(w < 1) 390 w = 1; 391 if(packflg) 392 packw = packflg; 393 break; 394 395 case Ael1: /* initial align of struct element */ 396 for(v=t; v->etype==TARRAY; v=v->link) 397 ; 398 if(v->etype == TSTRUCT || v->etype == TUNION) 399 w = v->align; 400 else { 401 w = ewidth[v->etype]; 402 if(w == 8) 403 w = 4; 404 } 405 if(w < 1 || w > SZ_LONG) 406 fatal(Z, "align"); 407 if(packflg) 408 packw = packflg; 409 break; 410 411 case Ael2: /* width of a struct element */ 412 o += t->width; 413 break; 414 415 case Aarg0: /* initial passbyptr argument in arg list */ 416 if(typesuv[t->etype]) { 417 o = align(o, types[TIND], Aarg1, nil); 418 o = align(o, types[TIND], Aarg2, nil); 419 } 420 break; 421 422 case Aarg1: /* initial align of parameter */ 423 w = ewidth[t->etype]; 424 if(w <= 0 || w >= SZ_LONG) { 425 w = SZ_LONG; 426 break; 427 } 428 w = 1; /* little endian no adjustment */ 429 break; 430 431 case Aarg2: /* width of a parameter */ 432 o += t->width; 433 w = t->width; 434 if(w > SZ_LONG) 435 w = SZ_LONG; 436 break; 437 438 case Aaut3: /* total align of automatic */ 439 o = align(o, t, Ael2, nil); 440 o = align(o, t, Ael1, nil); 441 w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */ 442 break; 443 } 444 if(packw != 0 && xround(o, w) != xround(o, packw)) 445 diag(Z, "#pragma pack changes offset of %T", t); 446 o = xround(o, w); 447 if(maxalign != nil && *maxalign < w) 448 *maxalign = w; 449 if(debug['A']) 450 print("align %s %d %T = %d\n", bnames[op], i, t, o); 451 return o; 452 } 453 454 int32 455 maxround(int32 max, int32 v) 456 { 457 v = xround(v, SZ_LONG); 458 if(v > max) 459 return v; 460 return max; 461 }