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