github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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(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.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.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	zname(Biobuf*, Sym*, int);
   355  char*	zaddr(char*, Adr*, int);
   356  void	zwrite(Biobuf*, Prog*, int, int);
   357  void	outhist(Biobuf*);
   358  
   359  void
   360  zwrite(Biobuf *b, Prog *p, int sf, int st)
   361  {
   362  	char bf[100], *bp;
   363  
   364  	bf[0] = p->as;
   365  	bf[1] = p->scond;
   366  	bf[2] = p->reg;
   367  	bf[3] = p->lineno;
   368  	bf[4] = p->lineno>>8;
   369  	bf[5] = p->lineno>>16;
   370  	bf[6] = p->lineno>>24;
   371  	bp = zaddr(bf+7, &p->from, sf);
   372  	bp = zaddr(bp, &p->to, st);
   373  	Bwrite(b, bf, bp-bf);
   374  }
   375  
   376  void
   377  outcode(void)
   378  {
   379  	struct { Sym *sym; short type; } h[NSYM];
   380  	Prog *p;
   381  	Sym *s;
   382  	int sf, st, t, sym;
   383  
   384  	if(debug['S']) {
   385  		for(p = firstp; p != P; p = p->link)
   386  			if(p->as != ADATA && p->as != AGLOBL)
   387  				pc--;
   388  		for(p = firstp; p != P; p = p->link) {
   389  			print("%P\n", p);
   390  			if(p->as != ADATA && p->as != AGLOBL)
   391  				pc++;
   392  		}
   393  	}
   394  
   395  	Bprint(&outbuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
   396  	if(pragcgobuf.to > pragcgobuf.start) {
   397  		Bprint(&outbuf, "\n");
   398  		Bprint(&outbuf, "$$  // exports\n\n");
   399  		Bprint(&outbuf, "$$  // local types\n\n");
   400  		Bprint(&outbuf, "$$  // cgo\n");
   401  		Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
   402  		Bprint(&outbuf, "\n$$\n\n");
   403  	}
   404  	Bprint(&outbuf, "!\n");
   405  
   406  	outhist(&outbuf);
   407  	for(sym=0; sym<NSYM; sym++) {
   408  		h[sym].sym = S;
   409  		h[sym].type = 0;
   410  	}
   411  	sym = 1;
   412  	for(p = firstp; p != P; p = p->link) {
   413  	jackpot:
   414  		sf = 0;
   415  		s = p->from.sym;
   416  		while(s != S) {
   417  			sf = s->sym;
   418  			if(sf < 0 || sf >= NSYM)
   419  				sf = 0;
   420  			t = p->from.name;
   421  			if(h[sf].type == t)
   422  			if(h[sf].sym == s)
   423  				break;
   424  			s->sym = sym;
   425  			zname(&outbuf, s, t);
   426  			h[sym].sym = s;
   427  			h[sym].type = t;
   428  			sf = sym;
   429  			sym++;
   430  			if(sym >= NSYM)
   431  				sym = 1;
   432  			break;
   433  		}
   434  		st = 0;
   435  		s = p->to.sym;
   436  		while(s != S) {
   437  			st = s->sym;
   438  			if(st < 0 || st >= NSYM)
   439  				st = 0;
   440  			t = p->to.name;
   441  			if(h[st].type == t)
   442  			if(h[st].sym == s)
   443  				break;
   444  			s->sym = sym;
   445  			zname(&outbuf, s, t);
   446  			h[sym].sym = s;
   447  			h[sym].type = t;
   448  			st = sym;
   449  			sym++;
   450  			if(sym >= NSYM)
   451  				sym = 1;
   452  			if(st == sf)
   453  				goto jackpot;
   454  			break;
   455  		}
   456  		zwrite(&outbuf, p, sf, st);
   457  	}
   458  	firstp = P;
   459  	lastp = P;
   460  }
   461  
   462  void
   463  outhist(Biobuf *b)
   464  {
   465  	Hist *h;
   466  	char *p, *q, *op, c;
   467  	Prog pg;
   468  	int n;
   469  	char *tofree;
   470  	static int first = 1;
   471  	static char *goroot, *goroot_final;
   472  
   473  	if(first) {
   474  		// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
   475  		first = 0;
   476  		goroot = getenv("GOROOT");
   477  		goroot_final = getenv("GOROOT_FINAL");
   478  		if(goroot == nil)
   479  			goroot = "";
   480  		if(goroot_final == nil)
   481  			goroot_final = goroot;
   482  		if(strcmp(goroot, goroot_final) == 0) {
   483  			goroot = nil;
   484  			goroot_final = nil;
   485  		}
   486  	}
   487  
   488  	tofree = nil;
   489  	pg = zprog;
   490  	pg.as = AHISTORY;
   491  	c = pathchar();
   492  	for(h = hist; h != H; h = h->link) {
   493  		p = h->name;
   494  		if(p != nil && goroot != nil) {
   495  			n = strlen(goroot);
   496  			if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
   497  				tofree = smprint("%s%s", goroot_final, p+n);
   498  				p = tofree;
   499  			}
   500  		}
   501  		op = 0;
   502  		if(systemtype(Windows) && p && p[1] == ':'){
   503  			c = p[2];
   504  		} else if(p && p[0] != c && h->offset == 0 && pathname){
   505  			if(systemtype(Windows) && pathname[1] == ':') {
   506  				op = p;
   507  				p = pathname;
   508  				c = p[2];
   509  			} else if(pathname[0] == c){
   510  				op = p;
   511  				p = pathname;
   512  			}
   513  		}
   514  		while(p) {
   515  			q = utfrune(p, c);
   516  			if(q) {
   517  				n = q-p;
   518  				if(n == 0){
   519  					n = 1;	/* leading "/" */
   520  					*p = '/';	/* don't emit "\" on windows */
   521  				}
   522  				q++;
   523  			} else {
   524  				n = strlen(p);
   525  				q = 0;
   526  			}
   527  			if(n) {
   528  				BPUTC(b, ANAME);
   529  				BPUTC(b, D_FILE);
   530  				BPUTC(b, 1);
   531  				BPUTC(b, '<');
   532  				Bwrite(b, p, n);
   533  				BPUTC(b, 0);
   534  			}
   535  			p = q;
   536  			if(p == 0 && op) {
   537  				p = op;
   538  				op = 0;
   539  			}
   540  		}
   541  		pg.lineno = h->line;
   542  		pg.to.type = zprog.to.type;
   543  		pg.to.offset = h->offset;
   544  		if(h->offset)
   545  			pg.to.type = D_CONST;
   546  
   547  		zwrite(b, &pg, 0, 0);
   548  
   549   		if(tofree) {
   550   			free(tofree);
   551   			tofree = nil;
   552   		}
   553  	}
   554  }
   555  
   556  void
   557  zname(Biobuf *b, Sym *s, int t)
   558  {
   559  	char *n, bf[7];
   560  	uint32 sig;
   561  
   562  	n = s->name;
   563  	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
   564  		sig = sign(s);
   565  		bf[0] = ASIGNAME;
   566  		bf[1] = sig;
   567  		bf[2] = sig>>8;
   568  		bf[3] = sig>>16;
   569  		bf[4] = sig>>24;
   570  		bf[5] = t;
   571  		bf[6] = s->sym;
   572  		Bwrite(b, bf, 7);
   573  		s->sig = SIGDONE;
   574  	}
   575  	else{
   576  		bf[0] = ANAME;
   577  		bf[1] = t;	/* type */
   578  		bf[2] = s->sym;	/* sym */
   579  		Bwrite(b, bf, 3);
   580  	}
   581  	Bwrite(b, n, strlen(n)+1);
   582  }
   583  
   584  char*
   585  zaddr(char *bp, Adr *a, int s)
   586  {
   587  	int32 l;
   588  	Ieee e;
   589  
   590  	bp[0] = a->type;
   591  	bp[1] = a->reg;
   592  	bp[2] = s;
   593  	bp[3] = a->name;
   594  	bp[4] = 0;
   595  	bp += 5;
   596  	switch(a->type) {
   597  	default:
   598  		diag(Z, "unknown type %d in zaddr", a->type);
   599  
   600  	case D_NONE:
   601  	case D_REG:
   602  	case D_FREG:
   603  	case D_PSR:
   604  		break;
   605  
   606  	case D_CONST2:
   607  		l = a->offset2;
   608  		bp[0] = l;
   609  		bp[1] = l>>8;
   610  		bp[2] = l>>16;
   611  		bp[3] = l>>24;
   612  		bp += 4;	// fall through
   613  	case D_OREG:
   614  	case D_CONST:
   615  	case D_BRANCH:
   616  	case D_SHIFT:
   617  		l = a->offset;
   618  		bp[0] = l;
   619  		bp[1] = l>>8;
   620  		bp[2] = l>>16;
   621  		bp[3] = l>>24;
   622  		bp += 4;
   623  		break;
   624  
   625  	case D_SCONST:
   626  		memmove(bp, a->sval, NSNAME);
   627  		bp += NSNAME;
   628  		break;
   629  
   630  	case D_FCONST:
   631  		ieeedtod(&e, a->dval);
   632  		l = e.l;
   633  		bp[0] = l;
   634  		bp[1] = l>>8;
   635  		bp[2] = l>>16;
   636  		bp[3] = l>>24;
   637  		bp += 4;
   638  		l = e.h;
   639  		bp[0] = l;
   640  		bp[1] = l>>8;
   641  		bp[2] = l>>16;
   642  		bp[3] = l>>24;
   643  		bp += 4;
   644  		break;
   645  	}
   646  	return bp;
   647  }
   648  
   649  int32
   650  align(int32 i, Type *t, int op, int32 *maxalign)
   651  {
   652  	int32 o;
   653  	Type *v;
   654  	int w;
   655  
   656  	o = i;
   657  	w = 1;
   658  	switch(op) {
   659  	default:
   660  		diag(Z, "unknown align opcode %d", op);
   661  		break;
   662  
   663  	case Asu2:	/* padding at end of a struct */
   664  		w = *maxalign;
   665  		if(w < 1)
   666  			w = 1;
   667  		if(packflg)
   668  			w = packflg;
   669  		break;
   670  
   671  	case Ael1:	/* initial align of struct element */
   672  		for(v=t; v->etype==TARRAY; v=v->link)
   673  			;
   674  		if(v->etype == TSTRUCT || v->etype == TUNION)
   675  			w = v->align;
   676  		else {
   677  			w = ewidth[v->etype];
   678  			if(w == 8)
   679  				w = 4;
   680  		}
   681  		if(w < 1 || w > SZ_LONG)
   682  			fatal(Z, "align");
   683  		if(packflg) 
   684  			w = packflg;
   685  		break;
   686  
   687  	case Ael2:	/* width of a struct element */
   688  		o += t->width;
   689  		break;
   690  
   691  	case Aarg0:	/* initial passbyptr argument in arg list */
   692  		if(typesuv[t->etype]) {
   693  			o = align(o, types[TIND], Aarg1, nil);
   694  			o = align(o, types[TIND], Aarg2, nil);
   695  		}
   696  		break;
   697  
   698  	case Aarg1:	/* initial align of parameter */
   699  		w = ewidth[t->etype];
   700  		if(w <= 0 || w >= SZ_LONG) {
   701  			w = SZ_LONG;
   702  			break;
   703  		}
   704  		w = 1;		/* little endian no adjustment */
   705  		break;
   706  
   707  	case Aarg2:	/* width of a parameter */
   708  		o += t->width;
   709  		w = t->width;
   710  		if(w > SZ_LONG)
   711  			w = SZ_LONG;
   712  		break;
   713  
   714  	case Aaut3:	/* total align of automatic */
   715  		o = align(o, t, Ael2, nil);
   716  		o = align(o, t, Ael1, nil);
   717  		w = SZ_LONG;	/* because of a pun in cc/dcl.c:contig() */
   718  		break;
   719  	}
   720  	o = xround(o, w);
   721  	if(maxalign != nil && *maxalign < w)
   722  		*maxalign = w;
   723  	if(debug['A'])
   724  		print("align %s %d %T = %d\n", bnames[op], i, t, o);
   725  	return o;
   726  }
   727  
   728  int32
   729  maxround(int32 max, int32 v)
   730  {
   731  	v = xround(v, SZ_LONG);
   732  	if(v > max)
   733  		return v;
   734  	return max;
   735  }