github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8l/span.c (about)

     1  // Inferno utils/8l/span.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/8l/span.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  // Instruction layout.
    32  
    33  #include	"l.h"
    34  #include	"../ld/lib.h"
    35  #include	"../ld/elf.h"
    36  
    37  static int32	vaddr(Adr*, Reloc*);
    38  
    39  void
    40  span1(Sym *s)
    41  {
    42  	Prog *p, *q;
    43  	int32 c, v, loop;
    44  	uchar *bp;
    45  	int n, m, i;
    46  
    47  	cursym = s;
    48  
    49  	for(p = s->text; p != P; p = p->link) {
    50  		p->back = 2;	// use short branches first time through
    51  		if((q = p->pcond) != P && (q->back & 2))
    52  			p->back |= 1;	// backward jump
    53  
    54  		if(p->as == AADJSP) {
    55  			p->to.type = D_SP;
    56  			v = -p->from.offset;
    57  			p->from.offset = v;
    58  			p->as = AADDL;
    59  			if(v < 0) {
    60  				p->as = ASUBL;
    61  				v = -v;
    62  				p->from.offset = v;
    63  			}
    64  			if(v == 0)
    65  				p->as = ANOP;
    66  		}
    67  	}
    68  	
    69  	n = 0;
    70  	do {
    71  		loop = 0;
    72  		memset(s->r, 0, s->nr*sizeof s->r[0]);
    73  		s->nr = 0;
    74  		s->np = 0;
    75  		c = 0;
    76  		for(p = s->text; p != P; p = p->link) {
    77  			p->pc = c;
    78  
    79  			// process forward jumps to p
    80  			for(q = p->comefrom; q != P; q = q->forwd) {
    81  				v = p->pc - (q->pc + q->mark);
    82  				if(q->back & 2)	{	// short
    83  					if(v > 127) {
    84  						loop++;
    85  						q->back ^= 2;
    86  					}
    87  					if(q->as == AJCXZW)
    88  						s->p[q->pc+2] = v;
    89  					else
    90  						s->p[q->pc+1] = v;
    91  				} else {
    92  					bp = s->p + q->pc + q->mark - 4;
    93  					*bp++ = v;
    94  					*bp++ = v>>8;
    95  					*bp++ = v>>16;
    96  					*bp = v>>24;
    97  				}	
    98  			}
    99  			p->comefrom = P;
   100  
   101  			asmins(p);
   102  			p->pc = c;
   103  			m = andptr-and;
   104  			symgrow(s, p->pc+m);
   105  			memmove(s->p+p->pc, and, m);
   106  			p->mark = m;
   107  			c += m;
   108  		}
   109  		if(++n > 20) {
   110  			diag("span must be looping");
   111  			errorexit();
   112  		}
   113  	} while(loop);
   114  	s->size = c;
   115  
   116  	if(debug['a'] > 1) {
   117  		print("span1 %s %d (%d tries)\n %.6ux", s->name, s->size, n, 0);
   118  		for(i=0; i<s->np; i++) {
   119  			print(" %.2ux", s->p[i]);
   120  			if(i%16 == 15)
   121  				print("\n  %.6ux", i+1);
   122  		}
   123  		if(i%16)
   124  			print("\n");
   125  	
   126  		for(i=0; i<s->nr; i++) {
   127  			Reloc *r;
   128  			
   129  			r = &s->r[i];
   130  			print(" rel %#.4ux/%d %s%+d\n", r->off, r->siz, r->sym->name, r->add);
   131  		}
   132  	}
   133  }
   134  
   135  void
   136  span(void)
   137  {
   138  	Prog *p, *q;
   139  	int32 v;
   140  	int n;
   141  
   142  	if(debug['v'])
   143  		Bprint(&bso, "%5.2f span\n", cputime());
   144  
   145  	// NOTE(rsc): If we get rid of the globals we should
   146  	// be able to parallelize these iterations.
   147  	for(cursym = textp; cursym != nil; cursym = cursym->next) {
   148  		if(cursym->text == nil || cursym->text->link == nil)
   149  			continue;
   150  
   151  		// TODO: move into span1
   152  		for(p = cursym->text; p != P; p = p->link) {
   153  			n = 0;
   154  			if(p->to.type == D_BRANCH)
   155  				if(p->pcond == P)
   156  					p->pcond = p;
   157  			if((q = p->pcond) != P)
   158  				if(q->back != 2)
   159  					n = 1;
   160  			p->back = n;
   161  			if(p->as == AADJSP) {
   162  				p->to.type = D_SP;
   163  				v = -p->from.offset;
   164  				p->from.offset = v;
   165  				p->as = AADDL;
   166  				if(v < 0) {
   167  					p->as = ASUBL;
   168  					v = -v;
   169  					p->from.offset = v;
   170  				}
   171  				if(v == 0)
   172  					p->as = ANOP;
   173  			}
   174  		}
   175  		span1(cursym);
   176  	}
   177  }
   178  
   179  void
   180  xdefine(char *p, int t, int32 v)
   181  {
   182  	Sym *s;
   183  
   184  	s = lookup(p, 0);
   185  	s->type = t;
   186  	s->value = v;
   187  	s->reachable = 1;
   188  	s->special = 1;
   189  }
   190  
   191  void
   192  instinit(void)
   193  {
   194  	int i;
   195  
   196  	for(i=1; optab[i].as; i++)
   197  		if(i != optab[i].as) {
   198  			diag("phase error in optab: at %A found %A", i, optab[i].as);
   199  			errorexit();
   200  		}
   201  	maxop = i;
   202  
   203  	for(i=0; i<Ymax; i++)
   204  		ycover[i*Ymax + i] = 1;
   205  
   206  	ycover[Yi0*Ymax + Yi8] = 1;
   207  	ycover[Yi1*Ymax + Yi8] = 1;
   208  
   209  	ycover[Yi0*Ymax + Yi32] = 1;
   210  	ycover[Yi1*Ymax + Yi32] = 1;
   211  	ycover[Yi8*Ymax + Yi32] = 1;
   212  
   213  	ycover[Yal*Ymax + Yrb] = 1;
   214  	ycover[Ycl*Ymax + Yrb] = 1;
   215  	ycover[Yax*Ymax + Yrb] = 1;
   216  	ycover[Ycx*Ymax + Yrb] = 1;
   217  	ycover[Yrx*Ymax + Yrb] = 1;
   218  
   219  	ycover[Yax*Ymax + Yrx] = 1;
   220  	ycover[Ycx*Ymax + Yrx] = 1;
   221  
   222  	ycover[Yax*Ymax + Yrl] = 1;
   223  	ycover[Ycx*Ymax + Yrl] = 1;
   224  	ycover[Yrx*Ymax + Yrl] = 1;
   225  
   226  	ycover[Yf0*Ymax + Yrf] = 1;
   227  
   228  	ycover[Yal*Ymax + Ymb] = 1;
   229  	ycover[Ycl*Ymax + Ymb] = 1;
   230  	ycover[Yax*Ymax + Ymb] = 1;
   231  	ycover[Ycx*Ymax + Ymb] = 1;
   232  	ycover[Yrx*Ymax + Ymb] = 1;
   233  	ycover[Yrb*Ymax + Ymb] = 1;
   234  	ycover[Ym*Ymax + Ymb] = 1;
   235  
   236  	ycover[Yax*Ymax + Yml] = 1;
   237  	ycover[Ycx*Ymax + Yml] = 1;
   238  	ycover[Yrx*Ymax + Yml] = 1;
   239  	ycover[Yrl*Ymax + Yml] = 1;
   240  	ycover[Ym*Ymax + Yml] = 1;
   241  
   242  	ycover[Yax*Ymax + Ymm] = 1;
   243  	ycover[Ycx*Ymax + Ymm] = 1;
   244  	ycover[Yrx*Ymax + Ymm] = 1;
   245  	ycover[Yrl*Ymax + Ymm] = 1;
   246  	ycover[Ym*Ymax + Ymm] = 1;
   247  	ycover[Ymr*Ymax + Ymm] = 1;
   248  
   249  	ycover[Ym*Ymax + Yxm] = 1;
   250  	ycover[Yxr*Ymax + Yxm] = 1;
   251  
   252  	for(i=0; i<D_NONE; i++) {
   253  		reg[i] = -1;
   254  		if(i >= D_AL && i <= D_BH)
   255  			reg[i] = (i-D_AL) & 7;
   256  		if(i >= D_AX && i <= D_DI)
   257  			reg[i] = (i-D_AX) & 7;
   258  		if(i >= D_F0 && i <= D_F0+7)
   259  			reg[i] = (i-D_F0) & 7;
   260  		if(i >= D_X0 && i <= D_X0+7)
   261  			reg[i] = (i-D_X0) & 7;
   262  	}
   263  }
   264  
   265  int
   266  prefixof(Adr *a)
   267  {
   268  	switch(a->type) {
   269  	case D_INDIR+D_CS:
   270  		return 0x2e;
   271  	case D_INDIR+D_DS:
   272  		return 0x3e;
   273  	case D_INDIR+D_ES:
   274  		return 0x26;
   275  	case D_INDIR+D_FS:
   276  		return 0x64;
   277  	case D_INDIR+D_GS:
   278  		return 0x65;
   279  	}
   280  	return 0;
   281  }
   282  
   283  int
   284  oclass(Adr *a)
   285  {
   286  	int32 v;
   287  
   288  	if((a->type >= D_INDIR && a->type < 2*D_INDIR) || a->index != D_NONE) {
   289  		if(a->index != D_NONE && a->scale == 0) {
   290  			if(a->type == D_ADDR) {
   291  				switch(a->index) {
   292  				case D_EXTERN:
   293  				case D_STATIC:
   294  					return Yi32;
   295  				case D_AUTO:
   296  				case D_PARAM:
   297  					return Yiauto;
   298  				}
   299  				return Yxxx;
   300  			}
   301  			//if(a->type == D_INDIR+D_ADDR)
   302  			//	print("*Ycol\n");
   303  			return Ycol;
   304  		}
   305  		return Ym;
   306  	}
   307  	switch(a->type)
   308  	{
   309  	case D_AL:
   310  		return Yal;
   311  
   312  	case D_AX:
   313  		return Yax;
   314  
   315  	case D_CL:
   316  	case D_DL:
   317  	case D_BL:
   318  	case D_AH:
   319  	case D_CH:
   320  	case D_DH:
   321  	case D_BH:
   322  		return Yrb;
   323  
   324  	case D_CX:
   325  		return Ycx;
   326  
   327  	case D_DX:
   328  	case D_BX:
   329  		return Yrx;
   330  
   331  	case D_SP:
   332  	case D_BP:
   333  	case D_SI:
   334  	case D_DI:
   335  		return Yrl;
   336  
   337  	case D_F0+0:
   338  		return	Yf0;
   339  
   340  	case D_F0+1:
   341  	case D_F0+2:
   342  	case D_F0+3:
   343  	case D_F0+4:
   344  	case D_F0+5:
   345  	case D_F0+6:
   346  	case D_F0+7:
   347  		return	Yrf;
   348  
   349  	case D_X0+0:
   350  	case D_X0+1:
   351  	case D_X0+2:
   352  	case D_X0+3:
   353  	case D_X0+4:
   354  	case D_X0+5:
   355  	case D_X0+6:
   356  	case D_X0+7:
   357  		return	Yxr;
   358  
   359  	case D_NONE:
   360  		return Ynone;
   361  
   362  	case D_CS:	return	Ycs;
   363  	case D_SS:	return	Yss;
   364  	case D_DS:	return	Yds;
   365  	case D_ES:	return	Yes;
   366  	case D_FS:	return	Yfs;
   367  	case D_GS:	return	Ygs;
   368  
   369  	case D_GDTR:	return	Ygdtr;
   370  	case D_IDTR:	return	Yidtr;
   371  	case D_LDTR:	return	Yldtr;
   372  	case D_MSW:	return	Ymsw;
   373  	case D_TASK:	return	Ytask;
   374  
   375  	case D_CR+0:	return	Ycr0;
   376  	case D_CR+1:	return	Ycr1;
   377  	case D_CR+2:	return	Ycr2;
   378  	case D_CR+3:	return	Ycr3;
   379  	case D_CR+4:	return	Ycr4;
   380  	case D_CR+5:	return	Ycr5;
   381  	case D_CR+6:	return	Ycr6;
   382  	case D_CR+7:	return	Ycr7;
   383  
   384  	case D_DR+0:	return	Ydr0;
   385  	case D_DR+1:	return	Ydr1;
   386  	case D_DR+2:	return	Ydr2;
   387  	case D_DR+3:	return	Ydr3;
   388  	case D_DR+4:	return	Ydr4;
   389  	case D_DR+5:	return	Ydr5;
   390  	case D_DR+6:	return	Ydr6;
   391  	case D_DR+7:	return	Ydr7;
   392  
   393  	case D_TR+0:	return	Ytr0;
   394  	case D_TR+1:	return	Ytr1;
   395  	case D_TR+2:	return	Ytr2;
   396  	case D_TR+3:	return	Ytr3;
   397  	case D_TR+4:	return	Ytr4;
   398  	case D_TR+5:	return	Ytr5;
   399  	case D_TR+6:	return	Ytr6;
   400  	case D_TR+7:	return	Ytr7;
   401  
   402  	case D_EXTERN:
   403  	case D_STATIC:
   404  	case D_AUTO:
   405  	case D_PARAM:
   406  		return Ym;
   407  
   408  	case D_CONST:
   409  	case D_CONST2:
   410  	case D_ADDR:
   411  		if(a->sym == S) {
   412  			v = a->offset;
   413  			if(v == 0)
   414  				return Yi0;
   415  			if(v == 1)
   416  				return Yi1;
   417  			if(v >= -128 && v <= 127)
   418  				return Yi8;
   419  		}
   420  		return Yi32;
   421  
   422  	case D_BRANCH:
   423  		return Ybr;
   424  	}
   425  	return Yxxx;
   426  }
   427  
   428  void
   429  asmidx(int scale, int index, int base)
   430  {
   431  	int i;
   432  
   433  	switch(index) {
   434  	default:
   435  		goto bad;
   436  
   437  	case D_NONE:
   438  		i = 4 << 3;
   439  		goto bas;
   440  
   441  	case D_AX:
   442  	case D_CX:
   443  	case D_DX:
   444  	case D_BX:
   445  	case D_BP:
   446  	case D_SI:
   447  	case D_DI:
   448  		i = reg[index] << 3;
   449  		break;
   450  	}
   451  	switch(scale) {
   452  	default:
   453  		goto bad;
   454  	case 1:
   455  		break;
   456  	case 2:
   457  		i |= (1<<6);
   458  		break;
   459  	case 4:
   460  		i |= (2<<6);
   461  		break;
   462  	case 8:
   463  		i |= (3<<6);
   464  		break;
   465  	}
   466  bas:
   467  	switch(base) {
   468  	default:
   469  		goto bad;
   470  	case D_NONE:	/* must be mod=00 */
   471  		i |= 5;
   472  		break;
   473  	case D_AX:
   474  	case D_CX:
   475  	case D_DX:
   476  	case D_BX:
   477  	case D_SP:
   478  	case D_BP:
   479  	case D_SI:
   480  	case D_DI:
   481  		i |= reg[base];
   482  		break;
   483  	}
   484  	*andptr++ = i;
   485  	return;
   486  bad:
   487  	diag("asmidx: bad address %d,%d,%d", scale, index, base);
   488  	*andptr++ = 0;
   489  	return;
   490  }
   491  
   492  static void
   493  put4(int32 v)
   494  {
   495  	andptr[0] = v;
   496  	andptr[1] = v>>8;
   497  	andptr[2] = v>>16;
   498  	andptr[3] = v>>24;
   499  	andptr += 4;
   500  }
   501  
   502  static void
   503  relput4(Prog *p, Adr *a)
   504  {
   505  	vlong v;
   506  	Reloc rel, *r;
   507  	
   508  	v = vaddr(a, &rel);
   509  	if(rel.siz != 0) {
   510  		if(rel.siz != 4)
   511  			diag("bad reloc");
   512  		r = addrel(cursym);
   513  		*r = rel;
   514  		r->off = p->pc + andptr - and;
   515  	}
   516  	put4(v);
   517  }
   518  
   519  int32
   520  symaddr(Sym *s)
   521  {
   522  	if(!s->reachable)
   523  		diag("unreachable symbol in symaddr - %s", s->name);
   524  	return s->value;
   525  }
   526  
   527  static int32
   528  vaddr(Adr *a, Reloc *r)
   529  {
   530  	int t;
   531  	int32 v;
   532  	Sym *s;
   533  	
   534  	if(r != nil)
   535  		memset(r, 0, sizeof *r);
   536  
   537  	t = a->type;
   538  	v = a->offset;
   539  	if(t == D_ADDR)
   540  		t = a->index;
   541  	switch(t) {
   542  	case D_STATIC:
   543  	case D_EXTERN:
   544  		s = a->sym;
   545  		if(s != nil) {
   546  			if(!s->reachable)
   547  				sysfatal("unreachable symbol in vaddr - %s", s->name);
   548  			if(r == nil) {
   549  				diag("need reloc for %D", a);
   550  				errorexit();
   551  			}
   552  			r->type = D_ADDR;
   553  			r->siz = 4;
   554  			r->off = -1;
   555  			r->sym = s;
   556  			r->add = v;
   557  			v = 0;
   558  		}
   559  	}
   560  	return v;
   561  }
   562  
   563  static int
   564  istls(Adr *a)
   565  {
   566  	if(HEADTYPE == Hlinux)
   567  		return a->index == D_GS;
   568  	return a->type == D_INDIR+D_GS;
   569  }
   570  
   571  void
   572  asmand(Adr *a, int r)
   573  {
   574  	int32 v;
   575  	int t, scale;
   576  	Reloc rel;
   577  
   578  	v = a->offset;
   579  	t = a->type;
   580  	rel.siz = 0;
   581  	if(a->index != D_NONE && a->index != D_FS && a->index != D_GS) {
   582  		if(t < D_INDIR || t >= 2*D_INDIR) {
   583  			switch(t) {
   584  			default:
   585  				goto bad;
   586  			case D_STATIC:
   587  			case D_EXTERN:
   588  				t = D_NONE;
   589  				v = vaddr(a, &rel);
   590  				break;
   591  			case D_AUTO:
   592  			case D_PARAM:
   593  				t = D_SP;
   594  				break;
   595  			}
   596  		} else
   597  			t -= D_INDIR;
   598  
   599  		if(t == D_NONE) {
   600  			*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
   601  			asmidx(a->scale, a->index, t);
   602  			goto putrelv;
   603  		}
   604  		if(v == 0 && rel.siz == 0 && t != D_BP) {
   605  			*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
   606  			asmidx(a->scale, a->index, t);
   607  			return;
   608  		}
   609  		if(v >= -128 && v < 128 && rel.siz == 0) {
   610  			*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
   611  			asmidx(a->scale, a->index, t);
   612  			*andptr++ = v;
   613  			return;
   614  		}
   615  		*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
   616  		asmidx(a->scale, a->index, t);
   617  		goto putrelv;
   618  	}
   619  	if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) {
   620  		if(v)
   621  			goto bad;
   622  		*andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
   623  		return;
   624  	}
   625  	
   626  	scale = a->scale;
   627  	if(t < D_INDIR || t >= 2*D_INDIR) {
   628  		switch(a->type) {
   629  		default:
   630  			goto bad;
   631  		case D_STATIC:
   632  		case D_EXTERN:
   633  			t = D_NONE;
   634  			v = vaddr(a, &rel);
   635  			break;
   636  		case D_AUTO:
   637  		case D_PARAM:
   638  			t = D_SP;
   639  			break;
   640  		}
   641  		scale = 1;
   642  	} else
   643  		t -= D_INDIR;
   644  
   645  	if(t == D_NONE || (D_CS <= t && t <= D_GS)) {
   646  		*andptr++ = (0 << 6) | (5 << 0) | (r << 3);
   647  		goto putrelv;
   648  	}
   649  	if(t == D_SP) {
   650  		if(v == 0 && rel.siz == 0) {
   651  			*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
   652  			asmidx(scale, D_NONE, t);
   653  			return;
   654  		}
   655  		if(v >= -128 && v < 128 && rel.siz == 0) {
   656  			*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
   657  			asmidx(scale, D_NONE, t);
   658  			*andptr++ = v;
   659  			return;
   660  		}
   661  		*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
   662  		asmidx(scale, D_NONE, t);
   663  		goto putrelv;
   664  	}
   665  	if(t >= D_AX && t <= D_DI) {
   666  		if(v == 0 && rel.siz == 0 && t != D_BP) {
   667  			*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
   668  			return;
   669  		}
   670  		if(v >= -128 && v < 128 && rel.siz == 0 && a->index != D_FS && a->index != D_GS) {
   671  			andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
   672  			andptr[1] = v;
   673  			andptr += 2;
   674  			return;
   675  		}
   676  		*andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
   677  		goto putrelv;
   678  	}
   679  	goto bad;
   680  
   681  putrelv:
   682  	if(rel.siz != 0) {
   683  		Reloc *r;
   684  		
   685  		if(rel.siz != 4) {
   686  			diag("bad rel");
   687  			goto bad;
   688  		}
   689  		r = addrel(cursym);
   690  		*r = rel;
   691  		r->off = curp->pc + andptr - and;
   692  	} else if(iself && linkmode == LinkExternal && istls(a) && HEADTYPE != Hopenbsd) {
   693  		Reloc *r;
   694  		Sym *s;
   695  
   696  		r = addrel(cursym);
   697  		r->off = curp->pc + andptr - and;
   698  		r->add = 0;
   699  		r->xadd = 0;
   700  		r->siz = 4;
   701  		r->type = D_TLS;
   702  		if(a->offset == tlsoffset+0)
   703  			s = lookup("runtime.g", 0);
   704  		else
   705  			s = lookup("runtime.m", 0);
   706  		s->type = STLSBSS;
   707  		s->reachable = 1;
   708  		s->hide = 1;
   709  		s->size = PtrSize;
   710  		r->sym = s;
   711  		r->xsym = s;
   712  		v = 0;
   713  	}
   714  
   715  	put4(v);
   716  	return;
   717  
   718  bad:
   719  	diag("asmand: bad address %D", a);
   720  	return;
   721  }
   722  
   723  #define	E	0xff
   724  uchar	ymovtab[] =
   725  {
   726  /* push */
   727  	APUSHL,	Ycs,	Ynone,	0,	0x0e,E,0,0,
   728  	APUSHL,	Yss,	Ynone,	0,	0x16,E,0,0,
   729  	APUSHL,	Yds,	Ynone,	0,	0x1e,E,0,0,
   730  	APUSHL,	Yes,	Ynone,	0,	0x06,E,0,0,
   731  	APUSHL,	Yfs,	Ynone,	0,	0x0f,0xa0,E,0,
   732  	APUSHL,	Ygs,	Ynone,	0,	0x0f,0xa8,E,0,
   733  
   734  	APUSHW,	Ycs,	Ynone,	0,	Pe,0x0e,E,0,
   735  	APUSHW,	Yss,	Ynone,	0,	Pe,0x16,E,0,
   736  	APUSHW,	Yds,	Ynone,	0,	Pe,0x1e,E,0,
   737  	APUSHW,	Yes,	Ynone,	0,	Pe,0x06,E,0,
   738  	APUSHW,	Yfs,	Ynone,	0,	Pe,0x0f,0xa0,E,
   739  	APUSHW,	Ygs,	Ynone,	0,	Pe,0x0f,0xa8,E,
   740  
   741  /* pop */
   742  	APOPL,	Ynone,	Yds,	0,	0x1f,E,0,0,
   743  	APOPL,	Ynone,	Yes,	0,	0x07,E,0,0,
   744  	APOPL,	Ynone,	Yss,	0,	0x17,E,0,0,
   745  	APOPL,	Ynone,	Yfs,	0,	0x0f,0xa1,E,0,
   746  	APOPL,	Ynone,	Ygs,	0,	0x0f,0xa9,E,0,
   747  
   748  	APOPW,	Ynone,	Yds,	0,	Pe,0x1f,E,0,
   749  	APOPW,	Ynone,	Yes,	0,	Pe,0x07,E,0,
   750  	APOPW,	Ynone,	Yss,	0,	Pe,0x17,E,0,
   751  	APOPW,	Ynone,	Yfs,	0,	Pe,0x0f,0xa1,E,
   752  	APOPW,	Ynone,	Ygs,	0,	Pe,0x0f,0xa9,E,
   753  
   754  /* mov seg */
   755  	AMOVW,	Yes,	Yml,	1,	0x8c,0,0,0,
   756  	AMOVW,	Ycs,	Yml,	1,	0x8c,1,0,0,
   757  	AMOVW,	Yss,	Yml,	1,	0x8c,2,0,0,
   758  	AMOVW,	Yds,	Yml,	1,	0x8c,3,0,0,
   759  	AMOVW,	Yfs,	Yml,	1,	0x8c,4,0,0,
   760  	AMOVW,	Ygs,	Yml,	1,	0x8c,5,0,0,
   761  
   762  	AMOVW,	Yml,	Yes,	2,	0x8e,0,0,0,
   763  	AMOVW,	Yml,	Ycs,	2,	0x8e,1,0,0,
   764  	AMOVW,	Yml,	Yss,	2,	0x8e,2,0,0,
   765  	AMOVW,	Yml,	Yds,	2,	0x8e,3,0,0,
   766  	AMOVW,	Yml,	Yfs,	2,	0x8e,4,0,0,
   767  	AMOVW,	Yml,	Ygs,	2,	0x8e,5,0,0,
   768  
   769  /* mov cr */
   770  	AMOVL,	Ycr0,	Yml,	3,	0x0f,0x20,0,0,
   771  	AMOVL,	Ycr2,	Yml,	3,	0x0f,0x20,2,0,
   772  	AMOVL,	Ycr3,	Yml,	3,	0x0f,0x20,3,0,
   773  	AMOVL,	Ycr4,	Yml,	3,	0x0f,0x20,4,0,
   774  
   775  	AMOVL,	Yml,	Ycr0,	4,	0x0f,0x22,0,0,
   776  	AMOVL,	Yml,	Ycr2,	4,	0x0f,0x22,2,0,
   777  	AMOVL,	Yml,	Ycr3,	4,	0x0f,0x22,3,0,
   778  	AMOVL,	Yml,	Ycr4,	4,	0x0f,0x22,4,0,
   779  
   780  /* mov dr */
   781  	AMOVL,	Ydr0,	Yml,	3,	0x0f,0x21,0,0,
   782  	AMOVL,	Ydr6,	Yml,	3,	0x0f,0x21,6,0,
   783  	AMOVL,	Ydr7,	Yml,	3,	0x0f,0x21,7,0,
   784  
   785  	AMOVL,	Yml,	Ydr0,	4,	0x0f,0x23,0,0,
   786  	AMOVL,	Yml,	Ydr6,	4,	0x0f,0x23,6,0,
   787  	AMOVL,	Yml,	Ydr7,	4,	0x0f,0x23,7,0,
   788  
   789  /* mov tr */
   790  	AMOVL,	Ytr6,	Yml,	3,	0x0f,0x24,6,0,
   791  	AMOVL,	Ytr7,	Yml,	3,	0x0f,0x24,7,0,
   792  
   793  	AMOVL,	Yml,	Ytr6,	4,	0x0f,0x26,6,E,
   794  	AMOVL,	Yml,	Ytr7,	4,	0x0f,0x26,7,E,
   795  
   796  /* lgdt, sgdt, lidt, sidt */
   797  	AMOVL,	Ym,	Ygdtr,	4,	0x0f,0x01,2,0,
   798  	AMOVL,	Ygdtr,	Ym,	3,	0x0f,0x01,0,0,
   799  	AMOVL,	Ym,	Yidtr,	4,	0x0f,0x01,3,0,
   800  	AMOVL,	Yidtr,	Ym,	3,	0x0f,0x01,1,0,
   801  
   802  /* lldt, sldt */
   803  	AMOVW,	Yml,	Yldtr,	4,	0x0f,0x00,2,0,
   804  	AMOVW,	Yldtr,	Yml,	3,	0x0f,0x00,0,0,
   805  
   806  /* lmsw, smsw */
   807  	AMOVW,	Yml,	Ymsw,	4,	0x0f,0x01,6,0,
   808  	AMOVW,	Ymsw,	Yml,	3,	0x0f,0x01,4,0,
   809  
   810  /* ltr, str */
   811  	AMOVW,	Yml,	Ytask,	4,	0x0f,0x00,3,0,
   812  	AMOVW,	Ytask,	Yml,	3,	0x0f,0x00,1,0,
   813  
   814  /* load full pointer */
   815  	AMOVL,	Yml,	Ycol,	5,	0,0,0,0,
   816  	AMOVW,	Yml,	Ycol,	5,	Pe,0,0,0,
   817  
   818  /* double shift */
   819  	ASHLL,	Ycol,	Yml,	6,	0xa4,0xa5,0,0,
   820  	ASHRL,	Ycol,	Yml,	6,	0xac,0xad,0,0,
   821  
   822  /* extra imul */
   823  	AIMULW,	Yml,	Yrl,	7,	Pq,0xaf,0,0,
   824  	AIMULL,	Yml,	Yrl,	7,	Pm,0xaf,0,0,
   825  	0
   826  };
   827  
   828  // byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
   829  // which is not referenced in a->type.
   830  // If a is empty, it returns BX to account for MULB-like instructions
   831  // that might use DX and AX.
   832  int
   833  byteswapreg(Adr *a)
   834  {
   835  	int cana, canb, canc, cand;
   836  
   837  	cana = canb = canc = cand = 1;
   838  
   839  	switch(a->type) {
   840  	case D_NONE:
   841  		cana = cand = 0;
   842  		break;
   843  	case D_AX:
   844  	case D_AL:
   845  	case D_AH:
   846  	case D_INDIR+D_AX:
   847  		cana = 0;
   848  		break;
   849  	case D_BX:
   850  	case D_BL:
   851  	case D_BH:
   852  	case D_INDIR+D_BX:
   853  		canb = 0;
   854  		break;
   855  	case D_CX:
   856  	case D_CL:
   857  	case D_CH:
   858  	case D_INDIR+D_CX:
   859  		canc = 0;
   860  		break;
   861  	case D_DX:
   862  	case D_DL:
   863  	case D_DH:
   864  	case D_INDIR+D_DX:
   865  		cand = 0;
   866  		break;
   867  	}
   868  	switch(a->index) {
   869  	case D_AX:
   870  		cana = 0;
   871  		break;
   872  	case D_BX:
   873  		canb = 0;
   874  		break;
   875  	case D_CX:
   876  		canc = 0;
   877  		break;
   878  	case D_DX:
   879  		cand = 0;
   880  		break;
   881  	}
   882  	if(cana)
   883  		return D_AX;
   884  	if(canb)
   885  		return D_BX;
   886  	if(canc)
   887  		return D_CX;
   888  	if(cand)
   889  		return D_DX;
   890  
   891  	diag("impossible byte register");
   892  	errorexit();
   893  	return 0;
   894  }
   895  
   896  void
   897  subreg(Prog *p, int from, int to)
   898  {
   899  
   900  	if(debug['Q'])
   901  		print("\n%P	s/%R/%R/\n", p, from, to);
   902  
   903  	if(p->from.type == from) {
   904  		p->from.type = to;
   905  		p->ft = 0;
   906  	}
   907  	if(p->to.type == from) {
   908  		p->to.type = to;
   909  		p->tt = 0;
   910  	}
   911  
   912  	if(p->from.index == from) {
   913  		p->from.index = to;
   914  		p->ft = 0;
   915  	}
   916  	if(p->to.index == from) {
   917  		p->to.index = to;
   918  		p->tt = 0;
   919  	}
   920  
   921  	from += D_INDIR;
   922  	if(p->from.type == from) {
   923  		p->from.type = to+D_INDIR;
   924  		p->ft = 0;
   925  	}
   926  	if(p->to.type == from) {
   927  		p->to.type = to+D_INDIR;
   928  		p->tt = 0;
   929  	}
   930  
   931  	if(debug['Q'])
   932  		print("%P\n", p);
   933  }
   934  
   935  static int
   936  mediaop(Optab *o, int op, int osize, int z)
   937  {
   938  	switch(op){
   939  	case Pm:
   940  	case Pe:
   941  	case Pf2:
   942  	case Pf3:
   943  		if(osize != 1){
   944  			if(op != Pm)
   945  				*andptr++ = op;
   946  			*andptr++ = Pm;
   947  			op = o->op[++z];
   948  			break;
   949  		}
   950  	default:
   951  		if(andptr == and || andptr[-1] != Pm)
   952  			*andptr++ = Pm;
   953  		break;
   954  	}
   955  	*andptr++ = op;
   956  	return z;
   957  }
   958  
   959  void
   960  doasm(Prog *p)
   961  {
   962  	Optab *o;
   963  	Prog *q, pp;
   964  	uchar *t;
   965  	int z, op, ft, tt, breg;
   966  	int32 v, pre;
   967  	Reloc rel, *r;
   968  	Adr *a;
   969  	
   970  	curp = p;	// TODO
   971  
   972  	pre = prefixof(&p->from);
   973  	if(pre)
   974  		*andptr++ = pre;
   975  	pre = prefixof(&p->to);
   976  	if(pre)
   977  		*andptr++ = pre;
   978  
   979  	if(p->ft == 0)
   980  		p->ft = oclass(&p->from);
   981  	if(p->tt == 0)
   982  		p->tt = oclass(&p->to);
   983  
   984  	ft = p->ft * Ymax;
   985  	tt = p->tt * Ymax;
   986  	o = &optab[p->as];
   987  	t = o->ytab;
   988  	if(t == 0) {
   989  		diag("asmins: noproto %P", p);
   990  		return;
   991  	}
   992  	for(z=0; *t; z+=t[3],t+=4)
   993  		if(ycover[ft+t[0]])
   994  		if(ycover[tt+t[1]])
   995  			goto found;
   996  	goto domov;
   997  
   998  found:
   999  	switch(o->prefix) {
  1000  	case Pq:	/* 16 bit escape and opcode escape */
  1001  		*andptr++ = Pe;
  1002  		*andptr++ = Pm;
  1003  		break;
  1004  
  1005  	case Pf2:	/* xmm opcode escape */
  1006  	case Pf3:
  1007  		*andptr++ = o->prefix;
  1008  		*andptr++ = Pm;
  1009  		break;
  1010  
  1011  	case Pm:	/* opcode escape */
  1012  		*andptr++ = Pm;
  1013  		break;
  1014  
  1015  	case Pe:	/* 16 bit escape */
  1016  		*andptr++ = Pe;
  1017  		break;
  1018  
  1019  	case Pb:	/* botch */
  1020  		break;
  1021  	}
  1022  
  1023  	op = o->op[z];
  1024  	switch(t[2]) {
  1025  	default:
  1026  		diag("asmins: unknown z %d %P", t[2], p);
  1027  		return;
  1028  
  1029  	case Zpseudo:
  1030  		break;
  1031  
  1032  	case Zlit:
  1033  		for(; op = o->op[z]; z++)
  1034  			*andptr++ = op;
  1035  		break;
  1036  
  1037  	case Zlitm_r:
  1038  		for(; op = o->op[z]; z++)
  1039  			*andptr++ = op;
  1040  		asmand(&p->from, reg[p->to.type]);
  1041  		break;
  1042  
  1043  	case Zm_r:
  1044  		*andptr++ = op;
  1045  		asmand(&p->from, reg[p->to.type]);
  1046  		break;
  1047  
  1048  	case Zm2_r:
  1049  		*andptr++ = op;
  1050  		*andptr++ = o->op[z+1];
  1051  		asmand(&p->from, reg[p->to.type]);
  1052  		break;
  1053  
  1054  	case Zm_r_xm:
  1055  		mediaop(o, op, t[3], z);
  1056  		asmand(&p->from, reg[p->to.type]);
  1057  		break;
  1058  
  1059  	case Zm_r_i_xm:
  1060  		mediaop(o, op, t[3], z);
  1061  		asmand(&p->from, reg[p->to.type]);
  1062  		*andptr++ = p->to.offset;
  1063  		break;
  1064  
  1065  	case Zibm_r:
  1066  		while ((op = o->op[z++]) != 0)
  1067  			*andptr++ = op;
  1068  		asmand(&p->from, reg[p->to.type]);
  1069  		*andptr++ = p->to.offset;
  1070  		break;
  1071  
  1072  	case Zaut_r:
  1073  		*andptr++ = 0x8d;	/* leal */
  1074  		if(p->from.type != D_ADDR)
  1075  			diag("asmins: Zaut sb type ADDR");
  1076  		p->from.type = p->from.index;
  1077  		p->from.index = D_NONE;
  1078  		p->ft = 0;
  1079  		asmand(&p->from, reg[p->to.type]);
  1080  		p->from.index = p->from.type;
  1081  		p->from.type = D_ADDR;
  1082  		p->ft = 0;
  1083  		break;
  1084  
  1085  	case Zm_o:
  1086  		*andptr++ = op;
  1087  		asmand(&p->from, o->op[z+1]);
  1088  		break;
  1089  
  1090  	case Zr_m:
  1091  		*andptr++ = op;
  1092  		asmand(&p->to, reg[p->from.type]);
  1093  		break;
  1094  
  1095  	case Zr_m_xm:
  1096  		mediaop(o, op, t[3], z);
  1097  		asmand(&p->to, reg[p->from.type]);
  1098  		break;
  1099  
  1100  	case Zr_m_i_xm:
  1101  		mediaop(o, op, t[3], z);
  1102  		asmand(&p->to, reg[p->from.type]);
  1103  		*andptr++ = p->from.offset;
  1104  		break;
  1105  
  1106  	case Zo_m:
  1107  		*andptr++ = op;
  1108  		asmand(&p->to, o->op[z+1]);
  1109  		break;
  1110  
  1111  	case Zm_ibo:
  1112  		*andptr++ = op;
  1113  		asmand(&p->from, o->op[z+1]);
  1114  		*andptr++ = vaddr(&p->to, nil);
  1115  		break;
  1116  
  1117  	case Zibo_m:
  1118  		*andptr++ = op;
  1119  		asmand(&p->to, o->op[z+1]);
  1120  		*andptr++ = vaddr(&p->from, nil);
  1121  		break;
  1122  
  1123  	case Z_ib:
  1124  	case Zib_:
  1125  		if(t[2] == Zib_)
  1126  			a = &p->from;
  1127  		else
  1128  			a = &p->to;
  1129  		v = vaddr(a, nil);
  1130  		*andptr++ = op;
  1131  		*andptr++ = v;
  1132  		break;
  1133  
  1134  	case Zib_rp:
  1135  		*andptr++ = op + reg[p->to.type];
  1136  		*andptr++ = vaddr(&p->from, nil);
  1137  		break;
  1138  
  1139  	case Zil_rp:
  1140  		*andptr++ = op + reg[p->to.type];
  1141  		if(o->prefix == Pe) {
  1142  			v = vaddr(&p->from, nil);
  1143  			*andptr++ = v;
  1144  			*andptr++ = v>>8;
  1145  		}
  1146  		else
  1147  			relput4(p, &p->from);
  1148  		break;
  1149  
  1150  	case Zib_rr:
  1151  		*andptr++ = op;
  1152  		asmand(&p->to, reg[p->to.type]);
  1153  		*andptr++ = vaddr(&p->from, nil);
  1154  		break;
  1155  
  1156  	case Z_il:
  1157  	case Zil_:
  1158  		if(t[2] == Zil_)
  1159  			a = &p->from;
  1160  		else
  1161  			a = &p->to;
  1162  		*andptr++ = op;
  1163  		if(o->prefix == Pe) {
  1164  			v = vaddr(a, nil);
  1165  			*andptr++ = v;
  1166  			*andptr++ = v>>8;
  1167  		}
  1168  		else
  1169  			relput4(p, a);
  1170  		break;
  1171  
  1172  	case Zm_ilo:
  1173  	case Zilo_m:
  1174  		*andptr++ = op;
  1175  		if(t[2] == Zilo_m) {
  1176  			a = &p->from;
  1177  			asmand(&p->to, o->op[z+1]);
  1178  		} else {
  1179  			a = &p->to;
  1180  			asmand(&p->from, o->op[z+1]);
  1181  		}
  1182  		if(o->prefix == Pe) {
  1183  			v = vaddr(a, nil);
  1184  			*andptr++ = v;
  1185  			*andptr++ = v>>8;
  1186  		}
  1187  		else
  1188  			relput4(p, a);
  1189  		break;
  1190  
  1191  	case Zil_rr:
  1192  		*andptr++ = op;
  1193  		asmand(&p->to, reg[p->to.type]);
  1194  		if(o->prefix == Pe) {
  1195  			v = vaddr(&p->from, nil);
  1196  			*andptr++ = v;
  1197  			*andptr++ = v>>8;
  1198  		}
  1199  		else
  1200  			relput4(p, &p->from);
  1201  		break;
  1202  
  1203  	case Z_rp:
  1204  		*andptr++ = op + reg[p->to.type];
  1205  		break;
  1206  
  1207  	case Zrp_:
  1208  		*andptr++ = op + reg[p->from.type];
  1209  		break;
  1210  
  1211  	case Zclr:
  1212  		*andptr++ = op;
  1213  		asmand(&p->to, reg[p->to.type]);
  1214  		break;
  1215  	
  1216  	case Zcall:
  1217  		q = p->pcond;
  1218  		if(q == nil) {
  1219  			diag("call without target");
  1220  			errorexit();
  1221  		}
  1222  		if(q->as != ATEXT) {
  1223  			// Could handle this case by making D_PCREL
  1224  			// record the Prog* instead of the Sym*, but let's
  1225  			// wait until the need arises.
  1226  			diag("call of non-TEXT %P", q);
  1227  			errorexit();
  1228  		}
  1229  		*andptr++ = op;
  1230  		r = addrel(cursym);
  1231  		r->off = p->pc + andptr - and;
  1232  		r->type = D_PCREL;
  1233  		r->siz = 4;
  1234  		r->sym = q->from.sym;
  1235  		put4(0);
  1236  		break;
  1237  
  1238  	case Zbr:
  1239  	case Zjmp:
  1240  	case Zloop:
  1241  		q = p->pcond;
  1242  		if(q == nil) {
  1243  			diag("jmp/branch/loop without target");
  1244  			errorexit();
  1245  		}
  1246  		if(q->as == ATEXT) {
  1247  			// jump out of function
  1248  			if(t[2] == Zbr) {
  1249  				diag("branch to ATEXT");
  1250  				errorexit();
  1251  			}
  1252  			*andptr++ = o->op[z+1];
  1253  			r = addrel(cursym);
  1254  			r->off = p->pc + andptr - and;
  1255  			r->sym = q->from.sym;
  1256  			r->type = D_PCREL;
  1257  			r->siz = 4;
  1258  			put4(0);
  1259  			break;
  1260  		}
  1261  		
  1262  		// Assumes q is in this function.
  1263  		// TODO: Check in input, preserve in brchain.
  1264  		
  1265  		// Fill in backward jump now.
  1266  		if(p->back & 1) {
  1267  			v = q->pc - (p->pc + 2);
  1268  			if(v >= -128) {
  1269  				if(p->as == AJCXZW)
  1270  					*andptr++ = 0x67;
  1271  				*andptr++ = op;
  1272  				*andptr++ = v;
  1273  			} else if(t[2] == Zloop) {
  1274  				diag("loop too far: %P", p);
  1275  			} else {
  1276  				v -= 5-2;
  1277  				if(t[2] == Zbr) {
  1278  					*andptr++ = 0x0f;
  1279  					v--;
  1280  				}
  1281  				*andptr++ = o->op[z+1];
  1282  				*andptr++ = v;
  1283  				*andptr++ = v>>8;
  1284  				*andptr++ = v>>16;
  1285  				*andptr++ = v>>24;
  1286  			}
  1287  			break;
  1288  		}
  1289  
  1290  		// Annotate target; will fill in later.
  1291  		p->forwd = q->comefrom;
  1292  		q->comefrom = p;
  1293  		if(p->back & 2)	{ // short
  1294  			if(p->as == AJCXZW)
  1295  				*andptr++ = 0x67;
  1296  			*andptr++ = op;
  1297  			*andptr++ = 0;
  1298  		} else if(t[2] == Zloop) {
  1299  			diag("loop too far: %P", p);
  1300  		} else {
  1301  			if(t[2] == Zbr)
  1302  				*andptr++ = 0x0f;
  1303  			*andptr++ = o->op[z+1];
  1304  			*andptr++ = 0;
  1305  			*andptr++ = 0;
  1306  			*andptr++ = 0;
  1307  			*andptr++ = 0;
  1308  		}
  1309  		break;
  1310  
  1311  	case Zcallcon:
  1312  	case Zjmpcon:
  1313  		if(t[2] == Zcallcon)
  1314  			*andptr++ = op;
  1315  		else
  1316  			*andptr++ = o->op[z+1];
  1317  		r = addrel(cursym);
  1318  		r->off = p->pc + andptr - and;
  1319  		r->type = D_PCREL;
  1320  		r->siz = 4;
  1321  		r->add = p->to.offset;
  1322  		put4(0);
  1323  		break;
  1324  	
  1325  	case Zcallind:
  1326  		*andptr++ = op;
  1327  		*andptr++ = o->op[z+1];
  1328  		r = addrel(cursym);
  1329  		r->off = p->pc + andptr - and;
  1330  		r->type = D_ADDR;
  1331  		r->siz = 4;
  1332  		r->add = p->to.offset;
  1333  		r->sym = p->to.sym;
  1334  		put4(0);
  1335  		break;
  1336  
  1337  	case Zbyte:
  1338  		v = vaddr(&p->from, &rel);
  1339  		if(rel.siz != 0) {
  1340  			rel.siz = op;
  1341  			r = addrel(cursym);
  1342  			*r = rel;
  1343  			r->off = p->pc + andptr - and;
  1344  		}
  1345  		*andptr++ = v;
  1346  		if(op > 1) {
  1347  			*andptr++ = v>>8;
  1348  			if(op > 2) {
  1349  				*andptr++ = v>>16;
  1350  				*andptr++ = v>>24;
  1351  			}
  1352  		}
  1353  		break;
  1354  
  1355  	case Zmov:
  1356  		goto domov;
  1357  	}
  1358  	return;
  1359  
  1360  domov:
  1361  	for(t=ymovtab; *t; t+=8)
  1362  		if(p->as == t[0])
  1363  		if(ycover[ft+t[1]])
  1364  		if(ycover[tt+t[2]])
  1365  			goto mfound;
  1366  bad:
  1367  	/*
  1368  	 * here, the assembly has failed.
  1369  	 * if its a byte instruction that has
  1370  	 * unaddressable registers, try to
  1371  	 * exchange registers and reissue the
  1372  	 * instruction with the operands renamed.
  1373  	 */
  1374  	pp = *p;
  1375  	z = p->from.type;
  1376  	if(z >= D_BP && z <= D_DI) {
  1377  		if((breg = byteswapreg(&p->to)) != D_AX) {
  1378  			*andptr++ = 0x87;			/* xchg lhs,bx */
  1379  			asmand(&p->from, reg[breg]);
  1380  			subreg(&pp, z, breg);
  1381  			doasm(&pp);
  1382  			*andptr++ = 0x87;			/* xchg lhs,bx */
  1383  			asmand(&p->from, reg[breg]);
  1384  		} else {
  1385  			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
  1386  			subreg(&pp, z, D_AX);
  1387  			doasm(&pp);
  1388  			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
  1389  		}
  1390  		return;
  1391  	}
  1392  	z = p->to.type;
  1393  	if(z >= D_BP && z <= D_DI) {
  1394  		if((breg = byteswapreg(&p->from)) != D_AX) {
  1395  			*andptr++ = 0x87;			/* xchg rhs,bx */
  1396  			asmand(&p->to, reg[breg]);
  1397  			subreg(&pp, z, breg);
  1398  			doasm(&pp);
  1399  			*andptr++ = 0x87;			/* xchg rhs,bx */
  1400  			asmand(&p->to, reg[breg]);
  1401  		} else {
  1402  			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
  1403  			subreg(&pp, z, D_AX);
  1404  			doasm(&pp);
  1405  			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
  1406  		}
  1407  		return;
  1408  	}
  1409  	diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
  1410  	return;
  1411  
  1412  mfound:
  1413  	switch(t[3]) {
  1414  	default:
  1415  		diag("asmins: unknown mov %d %P", t[3], p);
  1416  		break;
  1417  
  1418  	case 0:	/* lit */
  1419  		for(z=4; t[z]!=E; z++)
  1420  			*andptr++ = t[z];
  1421  		break;
  1422  
  1423  	case 1:	/* r,m */
  1424  		*andptr++ = t[4];
  1425  		asmand(&p->to, t[5]);
  1426  		break;
  1427  
  1428  	case 2:	/* m,r */
  1429  		*andptr++ = t[4];
  1430  		asmand(&p->from, t[5]);
  1431  		break;
  1432  
  1433  	case 3:	/* r,m - 2op */
  1434  		*andptr++ = t[4];
  1435  		*andptr++ = t[5];
  1436  		asmand(&p->to, t[6]);
  1437  		break;
  1438  
  1439  	case 4:	/* m,r - 2op */
  1440  		*andptr++ = t[4];
  1441  		*andptr++ = t[5];
  1442  		asmand(&p->from, t[6]);
  1443  		break;
  1444  
  1445  	case 5:	/* load full pointer, trash heap */
  1446  		if(t[4])
  1447  			*andptr++ = t[4];
  1448  		switch(p->to.index) {
  1449  		default:
  1450  			goto bad;
  1451  		case D_DS:
  1452  			*andptr++ = 0xc5;
  1453  			break;
  1454  		case D_SS:
  1455  			*andptr++ = 0x0f;
  1456  			*andptr++ = 0xb2;
  1457  			break;
  1458  		case D_ES:
  1459  			*andptr++ = 0xc4;
  1460  			break;
  1461  		case D_FS:
  1462  			*andptr++ = 0x0f;
  1463  			*andptr++ = 0xb4;
  1464  			break;
  1465  		case D_GS:
  1466  			*andptr++ = 0x0f;
  1467  			*andptr++ = 0xb5;
  1468  			break;
  1469  		}
  1470  		asmand(&p->from, reg[p->to.type]);
  1471  		break;
  1472  
  1473  	case 6:	/* double shift */
  1474  		z = p->from.type;
  1475  		switch(z) {
  1476  		default:
  1477  			goto bad;
  1478  		case D_CONST:
  1479  			*andptr++ = 0x0f;
  1480  			*andptr++ = t[4];
  1481  			asmand(&p->to, reg[p->from.index]);
  1482  			*andptr++ = p->from.offset;
  1483  			break;
  1484  		case D_CL:
  1485  		case D_CX:
  1486  			*andptr++ = 0x0f;
  1487  			*andptr++ = t[5];
  1488  			asmand(&p->to, reg[p->from.index]);
  1489  			break;
  1490  		}
  1491  		break;
  1492  
  1493  	case 7: /* imul rm,r */
  1494  		if(t[4] == Pq) {
  1495  			*andptr++ = Pe;
  1496  			*andptr++ = Pm;
  1497  		} else
  1498  			*andptr++ = t[4];
  1499  		*andptr++ = t[5];
  1500  		asmand(&p->from, reg[p->to.type]);
  1501  		break;
  1502  	}
  1503  }
  1504  
  1505  void
  1506  asmins(Prog *p)
  1507  {
  1508  	andptr = and;
  1509  	doasm(p);
  1510  	if(andptr > and+sizeof and) {
  1511  		print("and[] is too short - %ld byte instruction\n", andptr - and);
  1512  		errorexit();
  1513  	}
  1514  }