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  }