github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/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  }