github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/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  }