github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/6c/swt.c (about) 1 // Inferno utils/6c/swt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6c/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 regalloc(&nreg, n, Z); 39 if(typev[n->type->etype]) 40 nreg.type = types[TVLONG]; 41 else 42 nreg.type = types[TLONG]; 43 cgen(n, &nreg); 44 swit2(q, nc, def, &nreg); 45 regfree(&nreg); 46 } 47 48 void 49 swit2(C1 *q, int nc, int32 def, Node *n) 50 { 51 C1 *r; 52 int i; 53 Prog *sp; 54 55 if(nc < 5) { 56 for(i=0; i<nc; i++) { 57 if(debug['W']) 58 print("case = %.8llux\n", q->val); 59 gcmp(OEQ, n, q->val); 60 patch(p, q->label); 61 q++; 62 } 63 gbranch(OGOTO); 64 patch(p, def); 65 return; 66 } 67 i = nc / 2; 68 r = q+i; 69 if(debug['W']) 70 print("case > %.8llux\n", r->val); 71 gcmp(OGT, n, r->val); 72 sp = p; 73 gbranch(OGOTO); 74 p->as = AJEQ; 75 patch(p, r->label); 76 swit2(q, i, def, n); 77 78 if(debug['W']) 79 print("case < %.8llux\n", r->val); 80 patch(sp, pc); 81 swit2(r+1, nc-i-1, def, n); 82 } 83 84 void 85 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 86 { 87 int sh; 88 int32 v; 89 Node *l; 90 91 /* 92 * n1 gets adjusted/masked value 93 * n2 gets address of cell 94 * n3 gets contents of cell 95 */ 96 l = b->left; 97 if(n2 != Z) { 98 regalloc(n1, l, nn); 99 reglcgen(n2, l, Z); 100 regalloc(n3, l, Z); 101 gmove(n2, n3); 102 gmove(n3, n1); 103 } else { 104 regalloc(n1, l, nn); 105 cgen(l, n1); 106 } 107 if(b->type->shift == 0 && typeu[b->type->etype]) { 108 v = ~0 + (1L << b->type->nbits); 109 gopcode(OAND, tfield, nodconst(v), n1); 110 } else { 111 sh = 32 - b->type->shift - b->type->nbits; 112 if(sh > 0) 113 gopcode(OASHL, tfield, nodconst(sh), n1); 114 sh += b->type->shift; 115 if(sh > 0) 116 if(typeu[b->type->etype]) 117 gopcode(OLSHR, tfield, nodconst(sh), n1); 118 else 119 gopcode(OASHR, tfield, nodconst(sh), n1); 120 } 121 } 122 123 void 124 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 125 { 126 int32 v; 127 Node nod; 128 int sh; 129 130 regalloc(&nod, b->left, Z); 131 v = ~0 + (1L << b->type->nbits); 132 gopcode(OAND, types[TLONG], nodconst(v), n1); 133 gmove(n1, &nod); 134 if(nn != Z) 135 gmove(n1, nn); 136 sh = b->type->shift; 137 if(sh > 0) 138 gopcode(OASHL, types[TLONG], nodconst(sh), &nod); 139 v <<= sh; 140 gopcode(OAND, types[TLONG], nodconst(~v), n3); 141 gopcode(OOR, types[TLONG], n3, &nod); 142 gmove(&nod, n2); 143 144 regfree(&nod); 145 regfree(n1); 146 regfree(n2); 147 regfree(n3); 148 } 149 150 int32 151 outstring(char *s, int32 n) 152 { 153 int32 r; 154 155 if(suppress) 156 return nstring; 157 r = nstring; 158 while(n) { 159 string[mnstring] = *s++; 160 mnstring++; 161 nstring++; 162 if(mnstring >= NSNAME) { 163 gpseudo(ADATA, symstring, nodconst(0L)); 164 p->from.offset += nstring - NSNAME; 165 p->from.scale = NSNAME; 166 p->to.type = D_SCONST; 167 memmove(p->to.u.sval, string, NSNAME); 168 mnstring = 0; 169 } 170 n--; 171 } 172 return r; 173 } 174 175 void 176 sextern(Sym *s, Node *a, int32 o, int32 w) 177 { 178 int32 e, lw; 179 180 for(e=0; e<w; e+=NSNAME) { 181 lw = NSNAME; 182 if(w-e < lw) 183 lw = w-e; 184 gpseudo(ADATA, s, nodconst(0L)); 185 p->from.offset += o+e; 186 p->from.scale = lw; 187 p->to.type = D_SCONST; 188 memmove(p->to.u.sval, a->cstring+e, lw); 189 } 190 } 191 192 void 193 gextern(Sym *s, Node *a, int32 o, int32 w) 194 { 195 if(0 && a->op == OCONST && typev[a->type->etype]) { 196 gpseudo(ADATA, s, lo64(a)); 197 p->from.offset += o; 198 p->from.scale = 4; 199 gpseudo(ADATA, s, hi64(a)); 200 p->from.offset += o + 4; 201 p->from.scale = 4; 202 return; 203 } 204 gpseudo(ADATA, s, a); 205 p->from.offset += o; 206 p->from.scale = w; 207 switch(p->to.type) { 208 default: 209 p->to.index = p->to.type; 210 p->to.type = D_ADDR; 211 case D_CONST: 212 case D_FCONST: 213 case D_ADDR: 214 break; 215 } 216 } 217 218 void 219 outcode(void) 220 { 221 int f; 222 Biobuf b; 223 224 f = open(outfile, OWRITE); 225 if(f < 0) { 226 diag(Z, "cannot open %s", outfile); 227 return; 228 } 229 Binit(&b, f, OWRITE); 230 231 Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion()); 232 if(pragcgobuf.to > pragcgobuf.start) { 233 Bprint(&b, "\n"); 234 Bprint(&b, "$$ // exports\n\n"); 235 Bprint(&b, "$$ // local types\n\n"); 236 Bprint(&b, "$$ // cgo\n"); 237 Bprint(&b, "%s", fmtstrflush(&pragcgobuf)); 238 Bprint(&b, "\n$$\n\n"); 239 } 240 Bprint(&b, "!\n"); 241 242 writeobj(ctxt, &b); 243 Bterm(&b); 244 close(f); 245 lastp = P; 246 } 247 248 int32 249 align(int32 i, Type *t, int op, int32 *maxalign) 250 { 251 int32 o; 252 Type *v; 253 int w, packw; 254 255 o = i; 256 w = 1; 257 packw = 0; 258 switch(op) { 259 default: 260 diag(Z, "unknown align opcode %d", op); 261 break; 262 263 case Asu2: /* padding at end of a struct */ 264 w = *maxalign; 265 if(w < 1) 266 w = 1; 267 if(packflg) 268 packw = packflg; 269 break; 270 271 case Ael1: /* initial align of struct element */ 272 for(v=t; v->etype==TARRAY; v=v->link) 273 ; 274 if(v->etype == TSTRUCT || v->etype == TUNION) 275 w = v->align; 276 else 277 w = ewidth[v->etype]; 278 if(w < 1 || w > SZ_VLONG) 279 fatal(Z, "align"); 280 if(packflg) 281 packw = packflg; 282 break; 283 284 case Ael2: /* width of a struct element */ 285 o += t->width; 286 break; 287 288 case Aarg0: /* initial passbyptr argument in arg list */ 289 if(typesu[t->etype]) { 290 o = align(o, types[TIND], Aarg1, nil); 291 o = align(o, types[TIND], Aarg2, nil); 292 } 293 break; 294 295 case Aarg1: /* initial align of parameter */ 296 if(ewidth[TIND] == 4) { 297 if(typesu[t->etype]) { 298 for(v = t->link; v != T; v = v->down) 299 o = align(o, v, Aarg1, maxalign); 300 goto out; 301 } 302 w = ewidth[t->etype]; 303 if(typev[t->etype] || t->etype == TDOUBLE) 304 w = 8; 305 else if(w <= 0 || w >= 4) 306 w = 4; 307 else 308 w = 1; 309 break; 310 } 311 w = ewidth[t->etype]; 312 if(w <= 0 || w >= SZ_VLONG) { 313 w = SZ_VLONG; 314 break; 315 } 316 w = 1; /* little endian no adjustment */ 317 break; 318 319 case Aarg2: /* width of a parameter */ 320 o += t->width; 321 if(ewidth[TIND] == 4) { 322 o = align(o, t, Aarg1, maxalign); 323 goto out; 324 } 325 w = t->width; 326 if(w > SZ_VLONG) 327 w = SZ_VLONG; 328 break; 329 330 case Aaut3: /* total align of automatic */ 331 o = align(o, t, Ael1, nil); 332 o = align(o, t, Ael2, nil); 333 break; 334 } 335 if(packw != 0 && xround(o, w) != xround(o, packw)) 336 diag(Z, "#pragma pack changes offset of %T", t); 337 o = xround(o, w); 338 if(maxalign && *maxalign < w) 339 *maxalign = w; 340 out: 341 if(debug['A']) 342 print("align %s %d %T = %d\n", bnames[op], i, t, o); 343 return o; 344 } 345 346 int32 347 maxround(int32 max, int32 v) 348 { 349 v = xround(v, SZ_VLONG); 350 if(v > max) 351 return v; 352 return max; 353 }