github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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 = a->offset-tlsoffset;
   699  		r->xadd = r->add;
   700  		r->siz = 4;
   701  		r->type = D_TLS;
   702  		s = lookup("runtime.tlsgm", 0);
   703  		r->sym = s;
   704  		r->xsym = s;
   705  		v = 0;
   706  	}
   707  
   708  	put4(v);
   709  	return;
   710  
   711  bad:
   712  	diag("asmand: bad address %D", a);
   713  	return;
   714  }
   715  
   716  #define	E	0xff
   717  uchar	ymovtab[] =
   718  {
   719  /* push */
   720  	APUSHL,	Ycs,	Ynone,	0,	0x0e,E,0,0,
   721  	APUSHL,	Yss,	Ynone,	0,	0x16,E,0,0,
   722  	APUSHL,	Yds,	Ynone,	0,	0x1e,E,0,0,
   723  	APUSHL,	Yes,	Ynone,	0,	0x06,E,0,0,
   724  	APUSHL,	Yfs,	Ynone,	0,	0x0f,0xa0,E,0,
   725  	APUSHL,	Ygs,	Ynone,	0,	0x0f,0xa8,E,0,
   726  
   727  	APUSHW,	Ycs,	Ynone,	0,	Pe,0x0e,E,0,
   728  	APUSHW,	Yss,	Ynone,	0,	Pe,0x16,E,0,
   729  	APUSHW,	Yds,	Ynone,	0,	Pe,0x1e,E,0,
   730  	APUSHW,	Yes,	Ynone,	0,	Pe,0x06,E,0,
   731  	APUSHW,	Yfs,	Ynone,	0,	Pe,0x0f,0xa0,E,
   732  	APUSHW,	Ygs,	Ynone,	0,	Pe,0x0f,0xa8,E,
   733  
   734  /* pop */
   735  	APOPL,	Ynone,	Yds,	0,	0x1f,E,0,0,
   736  	APOPL,	Ynone,	Yes,	0,	0x07,E,0,0,
   737  	APOPL,	Ynone,	Yss,	0,	0x17,E,0,0,
   738  	APOPL,	Ynone,	Yfs,	0,	0x0f,0xa1,E,0,
   739  	APOPL,	Ynone,	Ygs,	0,	0x0f,0xa9,E,0,
   740  
   741  	APOPW,	Ynone,	Yds,	0,	Pe,0x1f,E,0,
   742  	APOPW,	Ynone,	Yes,	0,	Pe,0x07,E,0,
   743  	APOPW,	Ynone,	Yss,	0,	Pe,0x17,E,0,
   744  	APOPW,	Ynone,	Yfs,	0,	Pe,0x0f,0xa1,E,
   745  	APOPW,	Ynone,	Ygs,	0,	Pe,0x0f,0xa9,E,
   746  
   747  /* mov seg */
   748  	AMOVW,	Yes,	Yml,	1,	0x8c,0,0,0,
   749  	AMOVW,	Ycs,	Yml,	1,	0x8c,1,0,0,
   750  	AMOVW,	Yss,	Yml,	1,	0x8c,2,0,0,
   751  	AMOVW,	Yds,	Yml,	1,	0x8c,3,0,0,
   752  	AMOVW,	Yfs,	Yml,	1,	0x8c,4,0,0,
   753  	AMOVW,	Ygs,	Yml,	1,	0x8c,5,0,0,
   754  
   755  	AMOVW,	Yml,	Yes,	2,	0x8e,0,0,0,
   756  	AMOVW,	Yml,	Ycs,	2,	0x8e,1,0,0,
   757  	AMOVW,	Yml,	Yss,	2,	0x8e,2,0,0,
   758  	AMOVW,	Yml,	Yds,	2,	0x8e,3,0,0,
   759  	AMOVW,	Yml,	Yfs,	2,	0x8e,4,0,0,
   760  	AMOVW,	Yml,	Ygs,	2,	0x8e,5,0,0,
   761  
   762  /* mov cr */
   763  	AMOVL,	Ycr0,	Yml,	3,	0x0f,0x20,0,0,
   764  	AMOVL,	Ycr2,	Yml,	3,	0x0f,0x20,2,0,
   765  	AMOVL,	Ycr3,	Yml,	3,	0x0f,0x20,3,0,
   766  	AMOVL,	Ycr4,	Yml,	3,	0x0f,0x20,4,0,
   767  
   768  	AMOVL,	Yml,	Ycr0,	4,	0x0f,0x22,0,0,
   769  	AMOVL,	Yml,	Ycr2,	4,	0x0f,0x22,2,0,
   770  	AMOVL,	Yml,	Ycr3,	4,	0x0f,0x22,3,0,
   771  	AMOVL,	Yml,	Ycr4,	4,	0x0f,0x22,4,0,
   772  
   773  /* mov dr */
   774  	AMOVL,	Ydr0,	Yml,	3,	0x0f,0x21,0,0,
   775  	AMOVL,	Ydr6,	Yml,	3,	0x0f,0x21,6,0,
   776  	AMOVL,	Ydr7,	Yml,	3,	0x0f,0x21,7,0,
   777  
   778  	AMOVL,	Yml,	Ydr0,	4,	0x0f,0x23,0,0,
   779  	AMOVL,	Yml,	Ydr6,	4,	0x0f,0x23,6,0,
   780  	AMOVL,	Yml,	Ydr7,	4,	0x0f,0x23,7,0,
   781  
   782  /* mov tr */
   783  	AMOVL,	Ytr6,	Yml,	3,	0x0f,0x24,6,0,
   784  	AMOVL,	Ytr7,	Yml,	3,	0x0f,0x24,7,0,
   785  
   786  	AMOVL,	Yml,	Ytr6,	4,	0x0f,0x26,6,E,
   787  	AMOVL,	Yml,	Ytr7,	4,	0x0f,0x26,7,E,
   788  
   789  /* lgdt, sgdt, lidt, sidt */
   790  	AMOVL,	Ym,	Ygdtr,	4,	0x0f,0x01,2,0,
   791  	AMOVL,	Ygdtr,	Ym,	3,	0x0f,0x01,0,0,
   792  	AMOVL,	Ym,	Yidtr,	4,	0x0f,0x01,3,0,
   793  	AMOVL,	Yidtr,	Ym,	3,	0x0f,0x01,1,0,
   794  
   795  /* lldt, sldt */
   796  	AMOVW,	Yml,	Yldtr,	4,	0x0f,0x00,2,0,
   797  	AMOVW,	Yldtr,	Yml,	3,	0x0f,0x00,0,0,
   798  
   799  /* lmsw, smsw */
   800  	AMOVW,	Yml,	Ymsw,	4,	0x0f,0x01,6,0,
   801  	AMOVW,	Ymsw,	Yml,	3,	0x0f,0x01,4,0,
   802  
   803  /* ltr, str */
   804  	AMOVW,	Yml,	Ytask,	4,	0x0f,0x00,3,0,
   805  	AMOVW,	Ytask,	Yml,	3,	0x0f,0x00,1,0,
   806  
   807  /* load full pointer */
   808  	AMOVL,	Yml,	Ycol,	5,	0,0,0,0,
   809  	AMOVW,	Yml,	Ycol,	5,	Pe,0,0,0,
   810  
   811  /* double shift */
   812  	ASHLL,	Ycol,	Yml,	6,	0xa4,0xa5,0,0,
   813  	ASHRL,	Ycol,	Yml,	6,	0xac,0xad,0,0,
   814  
   815  /* extra imul */
   816  	AIMULW,	Yml,	Yrl,	7,	Pq,0xaf,0,0,
   817  	AIMULL,	Yml,	Yrl,	7,	Pm,0xaf,0,0,
   818  	0
   819  };
   820  
   821  // byteswapreg returns a byte-addressable register (AX, BX, CX, DX)
   822  // which is not referenced in a->type.
   823  // If a is empty, it returns BX to account for MULB-like instructions
   824  // that might use DX and AX.
   825  int
   826  byteswapreg(Adr *a)
   827  {
   828  	int cana, canb, canc, cand;
   829  
   830  	cana = canb = canc = cand = 1;
   831  
   832  	switch(a->type) {
   833  	case D_NONE:
   834  		cana = cand = 0;
   835  		break;
   836  	case D_AX:
   837  	case D_AL:
   838  	case D_AH:
   839  	case D_INDIR+D_AX:
   840  		cana = 0;
   841  		break;
   842  	case D_BX:
   843  	case D_BL:
   844  	case D_BH:
   845  	case D_INDIR+D_BX:
   846  		canb = 0;
   847  		break;
   848  	case D_CX:
   849  	case D_CL:
   850  	case D_CH:
   851  	case D_INDIR+D_CX:
   852  		canc = 0;
   853  		break;
   854  	case D_DX:
   855  	case D_DL:
   856  	case D_DH:
   857  	case D_INDIR+D_DX:
   858  		cand = 0;
   859  		break;
   860  	}
   861  	switch(a->index) {
   862  	case D_AX:
   863  		cana = 0;
   864  		break;
   865  	case D_BX:
   866  		canb = 0;
   867  		break;
   868  	case D_CX:
   869  		canc = 0;
   870  		break;
   871  	case D_DX:
   872  		cand = 0;
   873  		break;
   874  	}
   875  	if(cana)
   876  		return D_AX;
   877  	if(canb)
   878  		return D_BX;
   879  	if(canc)
   880  		return D_CX;
   881  	if(cand)
   882  		return D_DX;
   883  
   884  	diag("impossible byte register");
   885  	errorexit();
   886  	return 0;
   887  }
   888  
   889  void
   890  subreg(Prog *p, int from, int to)
   891  {
   892  
   893  	if(debug['Q'])
   894  		print("\n%P	s/%R/%R/\n", p, from, to);
   895  
   896  	if(p->from.type == from) {
   897  		p->from.type = to;
   898  		p->ft = 0;
   899  	}
   900  	if(p->to.type == from) {
   901  		p->to.type = to;
   902  		p->tt = 0;
   903  	}
   904  
   905  	if(p->from.index == from) {
   906  		p->from.index = to;
   907  		p->ft = 0;
   908  	}
   909  	if(p->to.index == from) {
   910  		p->to.index = to;
   911  		p->tt = 0;
   912  	}
   913  
   914  	from += D_INDIR;
   915  	if(p->from.type == from) {
   916  		p->from.type = to+D_INDIR;
   917  		p->ft = 0;
   918  	}
   919  	if(p->to.type == from) {
   920  		p->to.type = to+D_INDIR;
   921  		p->tt = 0;
   922  	}
   923  
   924  	if(debug['Q'])
   925  		print("%P\n", p);
   926  }
   927  
   928  static int
   929  mediaop(Optab *o, int op, int osize, int z)
   930  {
   931  	switch(op){
   932  	case Pm:
   933  	case Pe:
   934  	case Pf2:
   935  	case Pf3:
   936  		if(osize != 1){
   937  			if(op != Pm)
   938  				*andptr++ = op;
   939  			*andptr++ = Pm;
   940  			op = o->op[++z];
   941  			break;
   942  		}
   943  	default:
   944  		if(andptr == and || andptr[-1] != Pm)
   945  			*andptr++ = Pm;
   946  		break;
   947  	}
   948  	*andptr++ = op;
   949  	return z;
   950  }
   951  
   952  void
   953  doasm(Prog *p)
   954  {
   955  	Optab *o;
   956  	Prog *q, pp;
   957  	uchar *t;
   958  	int z, op, ft, tt, breg;
   959  	int32 v, pre;
   960  	Reloc rel, *r;
   961  	Adr *a;
   962  	
   963  	curp = p;	// TODO
   964  
   965  	pre = prefixof(&p->from);
   966  	if(pre)
   967  		*andptr++ = pre;
   968  	pre = prefixof(&p->to);
   969  	if(pre)
   970  		*andptr++ = pre;
   971  
   972  	if(p->ft == 0)
   973  		p->ft = oclass(&p->from);
   974  	if(p->tt == 0)
   975  		p->tt = oclass(&p->to);
   976  
   977  	ft = p->ft * Ymax;
   978  	tt = p->tt * Ymax;
   979  	o = &optab[p->as];
   980  	t = o->ytab;
   981  	if(t == 0) {
   982  		diag("asmins: noproto %P", p);
   983  		return;
   984  	}
   985  	for(z=0; *t; z+=t[3],t+=4)
   986  		if(ycover[ft+t[0]])
   987  		if(ycover[tt+t[1]])
   988  			goto found;
   989  	goto domov;
   990  
   991  found:
   992  	switch(o->prefix) {
   993  	case Pq:	/* 16 bit escape and opcode escape */
   994  		*andptr++ = Pe;
   995  		*andptr++ = Pm;
   996  		break;
   997  
   998  	case Pf2:	/* xmm opcode escape */
   999  	case Pf3:
  1000  		*andptr++ = o->prefix;
  1001  		*andptr++ = Pm;
  1002  		break;
  1003  
  1004  	case Pm:	/* opcode escape */
  1005  		*andptr++ = Pm;
  1006  		break;
  1007  
  1008  	case Pe:	/* 16 bit escape */
  1009  		*andptr++ = Pe;
  1010  		break;
  1011  
  1012  	case Pb:	/* botch */
  1013  		break;
  1014  	}
  1015  
  1016  	op = o->op[z];
  1017  	switch(t[2]) {
  1018  	default:
  1019  		diag("asmins: unknown z %d %P", t[2], p);
  1020  		return;
  1021  
  1022  	case Zpseudo:
  1023  		break;
  1024  
  1025  	case Zlit:
  1026  		for(; op = o->op[z]; z++)
  1027  			*andptr++ = op;
  1028  		break;
  1029  
  1030  	case Zlitm_r:
  1031  		for(; op = o->op[z]; z++)
  1032  			*andptr++ = op;
  1033  		asmand(&p->from, reg[p->to.type]);
  1034  		break;
  1035  
  1036  	case Zm_r:
  1037  		*andptr++ = op;
  1038  		asmand(&p->from, reg[p->to.type]);
  1039  		break;
  1040  
  1041  	case Zm2_r:
  1042  		*andptr++ = op;
  1043  		*andptr++ = o->op[z+1];
  1044  		asmand(&p->from, reg[p->to.type]);
  1045  		break;
  1046  
  1047  	case Zm_r_xm:
  1048  		mediaop(o, op, t[3], z);
  1049  		asmand(&p->from, reg[p->to.type]);
  1050  		break;
  1051  
  1052  	case Zm_r_i_xm:
  1053  		mediaop(o, op, t[3], z);
  1054  		asmand(&p->from, reg[p->to.type]);
  1055  		*andptr++ = p->to.offset;
  1056  		break;
  1057  
  1058  	case Zibm_r:
  1059  		while ((op = o->op[z++]) != 0)
  1060  			*andptr++ = op;
  1061  		asmand(&p->from, reg[p->to.type]);
  1062  		*andptr++ = p->to.offset;
  1063  		break;
  1064  
  1065  	case Zaut_r:
  1066  		*andptr++ = 0x8d;	/* leal */
  1067  		if(p->from.type != D_ADDR)
  1068  			diag("asmins: Zaut sb type ADDR");
  1069  		p->from.type = p->from.index;
  1070  		p->from.index = D_NONE;
  1071  		p->ft = 0;
  1072  		asmand(&p->from, reg[p->to.type]);
  1073  		p->from.index = p->from.type;
  1074  		p->from.type = D_ADDR;
  1075  		p->ft = 0;
  1076  		break;
  1077  
  1078  	case Zm_o:
  1079  		*andptr++ = op;
  1080  		asmand(&p->from, o->op[z+1]);
  1081  		break;
  1082  
  1083  	case Zr_m:
  1084  		*andptr++ = op;
  1085  		asmand(&p->to, reg[p->from.type]);
  1086  		break;
  1087  
  1088  	case Zr_m_xm:
  1089  		mediaop(o, op, t[3], z);
  1090  		asmand(&p->to, reg[p->from.type]);
  1091  		break;
  1092  
  1093  	case Zr_m_i_xm:
  1094  		mediaop(o, op, t[3], z);
  1095  		asmand(&p->to, reg[p->from.type]);
  1096  		*andptr++ = p->from.offset;
  1097  		break;
  1098  
  1099  	case Zo_m:
  1100  		*andptr++ = op;
  1101  		asmand(&p->to, o->op[z+1]);
  1102  		break;
  1103  
  1104  	case Zm_ibo:
  1105  		*andptr++ = op;
  1106  		asmand(&p->from, o->op[z+1]);
  1107  		*andptr++ = vaddr(&p->to, nil);
  1108  		break;
  1109  
  1110  	case Zibo_m:
  1111  		*andptr++ = op;
  1112  		asmand(&p->to, o->op[z+1]);
  1113  		*andptr++ = vaddr(&p->from, nil);
  1114  		break;
  1115  
  1116  	case Z_ib:
  1117  	case Zib_:
  1118  		if(t[2] == Zib_)
  1119  			a = &p->from;
  1120  		else
  1121  			a = &p->to;
  1122  		v = vaddr(a, nil);
  1123  		*andptr++ = op;
  1124  		*andptr++ = v;
  1125  		break;
  1126  
  1127  	case Zib_rp:
  1128  		*andptr++ = op + reg[p->to.type];
  1129  		*andptr++ = vaddr(&p->from, nil);
  1130  		break;
  1131  
  1132  	case Zil_rp:
  1133  		*andptr++ = op + reg[p->to.type];
  1134  		if(o->prefix == Pe) {
  1135  			v = vaddr(&p->from, nil);
  1136  			*andptr++ = v;
  1137  			*andptr++ = v>>8;
  1138  		}
  1139  		else
  1140  			relput4(p, &p->from);
  1141  		break;
  1142  
  1143  	case Zib_rr:
  1144  		*andptr++ = op;
  1145  		asmand(&p->to, reg[p->to.type]);
  1146  		*andptr++ = vaddr(&p->from, nil);
  1147  		break;
  1148  
  1149  	case Z_il:
  1150  	case Zil_:
  1151  		if(t[2] == Zil_)
  1152  			a = &p->from;
  1153  		else
  1154  			a = &p->to;
  1155  		*andptr++ = op;
  1156  		if(o->prefix == Pe) {
  1157  			v = vaddr(a, nil);
  1158  			*andptr++ = v;
  1159  			*andptr++ = v>>8;
  1160  		}
  1161  		else
  1162  			relput4(p, a);
  1163  		break;
  1164  
  1165  	case Zm_ilo:
  1166  	case Zilo_m:
  1167  		*andptr++ = op;
  1168  		if(t[2] == Zilo_m) {
  1169  			a = &p->from;
  1170  			asmand(&p->to, o->op[z+1]);
  1171  		} else {
  1172  			a = &p->to;
  1173  			asmand(&p->from, o->op[z+1]);
  1174  		}
  1175  		if(o->prefix == Pe) {
  1176  			v = vaddr(a, nil);
  1177  			*andptr++ = v;
  1178  			*andptr++ = v>>8;
  1179  		}
  1180  		else
  1181  			relput4(p, a);
  1182  		break;
  1183  
  1184  	case Zil_rr:
  1185  		*andptr++ = op;
  1186  		asmand(&p->to, reg[p->to.type]);
  1187  		if(o->prefix == Pe) {
  1188  			v = vaddr(&p->from, nil);
  1189  			*andptr++ = v;
  1190  			*andptr++ = v>>8;
  1191  		}
  1192  		else
  1193  			relput4(p, &p->from);
  1194  		break;
  1195  
  1196  	case Z_rp:
  1197  		*andptr++ = op + reg[p->to.type];
  1198  		break;
  1199  
  1200  	case Zrp_:
  1201  		*andptr++ = op + reg[p->from.type];
  1202  		break;
  1203  
  1204  	case Zclr:
  1205  		*andptr++ = op;
  1206  		asmand(&p->to, reg[p->to.type]);
  1207  		break;
  1208  	
  1209  	case Zcall:
  1210  		q = p->pcond;
  1211  		if(q == nil) {
  1212  			diag("call without target");
  1213  			errorexit();
  1214  		}
  1215  		if(q->as != ATEXT) {
  1216  			// Could handle this case by making D_PCREL
  1217  			// record the Prog* instead of the Sym*, but let's
  1218  			// wait until the need arises.
  1219  			diag("call of non-TEXT %P", q);
  1220  			errorexit();
  1221  		}
  1222  		*andptr++ = op;
  1223  		r = addrel(cursym);
  1224  		r->off = p->pc + andptr - and;
  1225  		r->type = D_PCREL;
  1226  		r->siz = 4;
  1227  		r->sym = q->from.sym;
  1228  		put4(0);
  1229  		break;
  1230  
  1231  	case Zbr:
  1232  	case Zjmp:
  1233  	case Zloop:
  1234  		q = p->pcond;
  1235  		if(q == nil) {
  1236  			diag("jmp/branch/loop without target");
  1237  			errorexit();
  1238  		}
  1239  		if(q->as == ATEXT) {
  1240  			// jump out of function
  1241  			if(t[2] == Zbr) {
  1242  				diag("branch to ATEXT");
  1243  				errorexit();
  1244  			}
  1245  			*andptr++ = o->op[z+1];
  1246  			r = addrel(cursym);
  1247  			r->off = p->pc + andptr - and;
  1248  			r->sym = q->from.sym;
  1249  			r->type = D_PCREL;
  1250  			r->siz = 4;
  1251  			put4(0);
  1252  			break;
  1253  		}
  1254  		
  1255  		// Assumes q is in this function.
  1256  		// TODO: Check in input, preserve in brchain.
  1257  		
  1258  		// Fill in backward jump now.
  1259  		if(p->back & 1) {
  1260  			v = q->pc - (p->pc + 2);
  1261  			if(v >= -128) {
  1262  				if(p->as == AJCXZW)
  1263  					*andptr++ = 0x67;
  1264  				*andptr++ = op;
  1265  				*andptr++ = v;
  1266  			} else if(t[2] == Zloop) {
  1267  				diag("loop too far: %P", p);
  1268  			} else {
  1269  				v -= 5-2;
  1270  				if(t[2] == Zbr) {
  1271  					*andptr++ = 0x0f;
  1272  					v--;
  1273  				}
  1274  				*andptr++ = o->op[z+1];
  1275  				*andptr++ = v;
  1276  				*andptr++ = v>>8;
  1277  				*andptr++ = v>>16;
  1278  				*andptr++ = v>>24;
  1279  			}
  1280  			break;
  1281  		}
  1282  
  1283  		// Annotate target; will fill in later.
  1284  		p->forwd = q->comefrom;
  1285  		q->comefrom = p;
  1286  		if(p->back & 2)	{ // short
  1287  			if(p->as == AJCXZW)
  1288  				*andptr++ = 0x67;
  1289  			*andptr++ = op;
  1290  			*andptr++ = 0;
  1291  		} else if(t[2] == Zloop) {
  1292  			diag("loop too far: %P", p);
  1293  		} else {
  1294  			if(t[2] == Zbr)
  1295  				*andptr++ = 0x0f;
  1296  			*andptr++ = o->op[z+1];
  1297  			*andptr++ = 0;
  1298  			*andptr++ = 0;
  1299  			*andptr++ = 0;
  1300  			*andptr++ = 0;
  1301  		}
  1302  		break;
  1303  
  1304  	case Zcallcon:
  1305  	case Zjmpcon:
  1306  		if(t[2] == Zcallcon)
  1307  			*andptr++ = op;
  1308  		else
  1309  			*andptr++ = o->op[z+1];
  1310  		r = addrel(cursym);
  1311  		r->off = p->pc + andptr - and;
  1312  		r->type = D_PCREL;
  1313  		r->siz = 4;
  1314  		r->add = p->to.offset;
  1315  		put4(0);
  1316  		break;
  1317  	
  1318  	case Zcallind:
  1319  		*andptr++ = op;
  1320  		*andptr++ = o->op[z+1];
  1321  		r = addrel(cursym);
  1322  		r->off = p->pc + andptr - and;
  1323  		r->type = D_ADDR;
  1324  		r->siz = 4;
  1325  		r->add = p->to.offset;
  1326  		r->sym = p->to.sym;
  1327  		put4(0);
  1328  		break;
  1329  
  1330  	case Zbyte:
  1331  		v = vaddr(&p->from, &rel);
  1332  		if(rel.siz != 0) {
  1333  			rel.siz = op;
  1334  			r = addrel(cursym);
  1335  			*r = rel;
  1336  			r->off = p->pc + andptr - and;
  1337  		}
  1338  		*andptr++ = v;
  1339  		if(op > 1) {
  1340  			*andptr++ = v>>8;
  1341  			if(op > 2) {
  1342  				*andptr++ = v>>16;
  1343  				*andptr++ = v>>24;
  1344  			}
  1345  		}
  1346  		break;
  1347  
  1348  	case Zmov:
  1349  		goto domov;
  1350  	}
  1351  	return;
  1352  
  1353  domov:
  1354  	for(t=ymovtab; *t; t+=8)
  1355  		if(p->as == t[0])
  1356  		if(ycover[ft+t[1]])
  1357  		if(ycover[tt+t[2]])
  1358  			goto mfound;
  1359  bad:
  1360  	/*
  1361  	 * here, the assembly has failed.
  1362  	 * if its a byte instruction that has
  1363  	 * unaddressable registers, try to
  1364  	 * exchange registers and reissue the
  1365  	 * instruction with the operands renamed.
  1366  	 */
  1367  	pp = *p;
  1368  	z = p->from.type;
  1369  	if(z >= D_BP && z <= D_DI) {
  1370  		if((breg = byteswapreg(&p->to)) != D_AX) {
  1371  			*andptr++ = 0x87;			/* xchg lhs,bx */
  1372  			asmand(&p->from, reg[breg]);
  1373  			subreg(&pp, z, breg);
  1374  			doasm(&pp);
  1375  			*andptr++ = 0x87;			/* xchg lhs,bx */
  1376  			asmand(&p->from, reg[breg]);
  1377  		} else {
  1378  			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
  1379  			subreg(&pp, z, D_AX);
  1380  			doasm(&pp);
  1381  			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
  1382  		}
  1383  		return;
  1384  	}
  1385  	z = p->to.type;
  1386  	if(z >= D_BP && z <= D_DI) {
  1387  		if((breg = byteswapreg(&p->from)) != D_AX) {
  1388  			*andptr++ = 0x87;			/* xchg rhs,bx */
  1389  			asmand(&p->to, reg[breg]);
  1390  			subreg(&pp, z, breg);
  1391  			doasm(&pp);
  1392  			*andptr++ = 0x87;			/* xchg rhs,bx */
  1393  			asmand(&p->to, reg[breg]);
  1394  		} else {
  1395  			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
  1396  			subreg(&pp, z, D_AX);
  1397  			doasm(&pp);
  1398  			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
  1399  		}
  1400  		return;
  1401  	}
  1402  	diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
  1403  	return;
  1404  
  1405  mfound:
  1406  	switch(t[3]) {
  1407  	default:
  1408  		diag("asmins: unknown mov %d %P", t[3], p);
  1409  		break;
  1410  
  1411  	case 0:	/* lit */
  1412  		for(z=4; t[z]!=E; z++)
  1413  			*andptr++ = t[z];
  1414  		break;
  1415  
  1416  	case 1:	/* r,m */
  1417  		*andptr++ = t[4];
  1418  		asmand(&p->to, t[5]);
  1419  		break;
  1420  
  1421  	case 2:	/* m,r */
  1422  		*andptr++ = t[4];
  1423  		asmand(&p->from, t[5]);
  1424  		break;
  1425  
  1426  	case 3:	/* r,m - 2op */
  1427  		*andptr++ = t[4];
  1428  		*andptr++ = t[5];
  1429  		asmand(&p->to, t[6]);
  1430  		break;
  1431  
  1432  	case 4:	/* m,r - 2op */
  1433  		*andptr++ = t[4];
  1434  		*andptr++ = t[5];
  1435  		asmand(&p->from, t[6]);
  1436  		break;
  1437  
  1438  	case 5:	/* load full pointer, trash heap */
  1439  		if(t[4])
  1440  			*andptr++ = t[4];
  1441  		switch(p->to.index) {
  1442  		default:
  1443  			goto bad;
  1444  		case D_DS:
  1445  			*andptr++ = 0xc5;
  1446  			break;
  1447  		case D_SS:
  1448  			*andptr++ = 0x0f;
  1449  			*andptr++ = 0xb2;
  1450  			break;
  1451  		case D_ES:
  1452  			*andptr++ = 0xc4;
  1453  			break;
  1454  		case D_FS:
  1455  			*andptr++ = 0x0f;
  1456  			*andptr++ = 0xb4;
  1457  			break;
  1458  		case D_GS:
  1459  			*andptr++ = 0x0f;
  1460  			*andptr++ = 0xb5;
  1461  			break;
  1462  		}
  1463  		asmand(&p->from, reg[p->to.type]);
  1464  		break;
  1465  
  1466  	case 6:	/* double shift */
  1467  		z = p->from.type;
  1468  		switch(z) {
  1469  		default:
  1470  			goto bad;
  1471  		case D_CONST:
  1472  			*andptr++ = 0x0f;
  1473  			*andptr++ = t[4];
  1474  			asmand(&p->to, reg[p->from.index]);
  1475  			*andptr++ = p->from.offset;
  1476  			break;
  1477  		case D_CL:
  1478  		case D_CX:
  1479  			*andptr++ = 0x0f;
  1480  			*andptr++ = t[5];
  1481  			asmand(&p->to, reg[p->from.index]);
  1482  			break;
  1483  		}
  1484  		break;
  1485  
  1486  	case 7: /* imul rm,r */
  1487  		if(t[4] == Pq) {
  1488  			*andptr++ = Pe;
  1489  			*andptr++ = Pm;
  1490  		} else
  1491  			*andptr++ = t[4];
  1492  		*andptr++ = t[5];
  1493  		asmand(&p->from, reg[p->to.type]);
  1494  		break;
  1495  	}
  1496  }
  1497  
  1498  void
  1499  asmins(Prog *p)
  1500  {
  1501  	andptr = and;
  1502  	doasm(p);
  1503  	if(andptr > and+sizeof and) {
  1504  		print("and[] is too short - %ld byte instruction\n", andptr - and);
  1505  		errorexit();
  1506  	}
  1507  }