changelog shortlog tags branches changeset file revisions annotate raw help

Mercurial > hg > plan9front / sys/src/cmd/7l/asm.c

revision 0: eaccc3e8d226
     1.1new file mode 100755
     1.2--- /dev/null
     1.3+++ b/sys/src/cmd/7l/asm.c
     1.4@@ -0,0 +1,1220 @@
     1.5+#include	"l.h"
     1.6+
     1.7+#define	LPUT(c)\
     1.8+	{\
     1.9+		cbp[0] = (c);\
    1.10+		cbp[1] = (c)>>8;\
    1.11+		cbp[2] = (c)>>16;\
    1.12+		cbp[3] = (c)>>24;\
    1.13+		cbp += 4;\
    1.14+		cbc -= 4;\
    1.15+		if(cbc <= 0)\
    1.16+			cflush();\
    1.17+	}
    1.18+
    1.19+#define	CPUT(c)\
    1.20+	{\
    1.21+		cbp[0] = (c);\
    1.22+		cbp++;\
    1.23+		cbc--;\
    1.24+		if(cbc <= 0)\
    1.25+			cflush();\
    1.26+	}
    1.27+
    1.28+#define	VLPUT(c)\
    1.29+	{\
    1.30+		cbp[0] = (c);\
    1.31+		cbp[1] = (c)>>8;\
    1.32+		cbp[2] = (c)>>16;\
    1.33+		cbp[3] = (c)>>24;\
    1.34+		cbp[4] = (c)>>32;\
    1.35+		cbp[5] = (c)>>40;\
    1.36+		cbp[6] = (c)>>48;\
    1.37+		cbp[7] = (c)>>56;\
    1.38+		cbp += 8;\
    1.39+		cbc -= 8;\
    1.40+		if(cbc <= 0)\
    1.41+			cflush();\
    1.42+	}
    1.43+#define	LPUTBE(c)\
    1.44+	{\
    1.45+		cbp[0] = (c)>>24;\
    1.46+		cbp[1] = (c)>>16;\
    1.47+		cbp[2] = (c)>>8;\
    1.48+		cbp[3] = (c);\
    1.49+		cbp += 4;\
    1.50+		cbc -= 4;\
    1.51+		if(cbc <= 0)\
    1.52+			cflush();\
    1.53+	}
    1.54+
    1.55+long
    1.56+entryvalue(void)
    1.57+{
    1.58+	char *a;
    1.59+	Sym *s;
    1.60+
    1.61+	a = INITENTRY;
    1.62+	if(*a >= '0' && *a <= '9')
    1.63+		return atolwhex(a);
    1.64+	s = lookup(a, 0);
    1.65+	if(s->type == 0)
    1.66+		return INITTEXT;
    1.67+	if(s->type != STEXT && s->type != SLEAF)
    1.68+		diag("entry not text: %s", s->name);
    1.69+	return s->value;
    1.70+}
    1.71+
    1.72+void
    1.73+asmb(void)
    1.74+{
    1.75+	Prog *p;
    1.76+	vlong t;
    1.77+	Optab *o;
    1.78+
    1.79+	if(debug['v'])
    1.80+		Bprint(&bso, "%5.2f asm\n", cputime());
    1.81+	Bflush(&bso);
    1.82+	seek(cout, HEADR, 0);
    1.83+	pc = INITTEXT;
    1.84+	for(p = firstp; p != P; p = p->link) {
    1.85+		if(p->as == ATEXT) {
    1.86+			curtext = p;
    1.87+			autosize = p->to.offset + 8;
    1.88+		}
    1.89+		if(p->pc != pc) {
    1.90+			diag("phase error %lux sb %lux",
    1.91+				p->pc, pc);
    1.92+			if(!debug['a'])
    1.93+				prasm(curp);
    1.94+			pc = p->pc;
    1.95+		}
    1.96+		if (p->as == AMOVQ || p->as == AMOVT) {
    1.97+			if ((p->from.reg == REGSP) && (p->from.offset&7) != 0
    1.98+			|| (p->to.reg == REGSP) && (p->to.offset&7) != 0)
    1.99+				diag("bad stack alignment: %P", p);
   1.100+			if ((p->from.reg == REGSB) && (p->from.offset&7) != 0
   1.101+			|| (p->to.reg == REGSB) && (p->to.offset&7) != 0)
   1.102+				diag("bad global alignment: %P", p);
   1.103+		}
   1.104+		curp = p;
   1.105+		o = oplook(p);	/* could probably avoid this call */
   1.106+		if(asmout(p, o)) {
   1.107+			p = p->link;
   1.108+			pc += 4;
   1.109+		}
   1.110+		pc += o->size;
   1.111+	}
   1.112+	if(debug['a'])
   1.113+		Bprint(&bso, "\n");
   1.114+	Bflush(&bso);
   1.115+	cflush();
   1.116+
   1.117+	curtext = P;
   1.118+	switch(HEADTYPE) {
   1.119+	case 0:
   1.120+		seek(cout, rnd(HEADR+textsize, 8192), 0);
   1.121+		break;
   1.122+	case 1:
   1.123+	case 2:
   1.124+	case 3:
   1.125+		seek(cout, HEADR+textsize, 0);
   1.126+		break;
   1.127+	}
   1.128+	for(t = 0; t < datsize; t += sizeof(buf)-100) {
   1.129+		if(datsize-t > sizeof(buf)-100)
   1.130+			datblk(t, sizeof(buf)-100);
   1.131+		else
   1.132+			datblk(t, datsize-t);
   1.133+	}
   1.134+
   1.135+	symsize = 0;
   1.136+	lcsize = 0;
   1.137+	if(!debug['s']) {
   1.138+		if(debug['v'])
   1.139+			Bprint(&bso, "%5.2f sym\n", cputime());
   1.140+		Bflush(&bso);
   1.141+		switch(HEADTYPE) {
   1.142+		case 0:
   1.143+			seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
   1.144+			break;
   1.145+		case 2:
   1.146+		case 1:
   1.147+		case 3:
   1.148+			seek(cout, HEADR+textsize+datsize, 0);
   1.149+			break;
   1.150+		}
   1.151+		if(!debug['s'])
   1.152+			asmsym();
   1.153+		if(debug['v'])
   1.154+			Bprint(&bso, "%5.2f pc\n", cputime());
   1.155+		Bflush(&bso);
   1.156+		if(!debug['s'])
   1.157+			asmlc();
   1.158+		cflush();
   1.159+	}
   1.160+
   1.161+	if(debug['v'])
   1.162+		Bprint(&bso, "%5.2f header\n", cputime());
   1.163+	Bflush(&bso);
   1.164+	seek(cout, 0L, 0);
   1.165+	switch(HEADTYPE) {
   1.166+	case 0:
   1.167+		lput(0x0183L);		/* magic and sections */
   1.168+		lput(0L);			/* time and date */
   1.169+		vlput(rnd(HEADR+textsize, 8192)+datsize);
   1.170+		lput(symsize);			/* nsyms */
   1.171+		lput(0x50L|(7L<<16));		/* size of optional hdr and flags */
   1.172+		lput(0413|(0x101L<<16));	/* magic and version */
   1.173+		lput(-1);			/* pad for alignment */
   1.174+
   1.175+		vlput(rnd(HEADR+textsize, 8192));		/* sizes */
   1.176+		vlput(datsize);
   1.177+		vlput(bsssize);
   1.178+		vlput(entryvalue());		/* va of entry */
   1.179+		vlput(INITTEXT-HEADR);		/* va of base of text */
   1.180+		vlput(INITDAT);			/* va of base of data */
   1.181+		vlput(INITDAT+datsize);		/* va of base of bss */
   1.182+		lput(~0L);			/* gp reg mask */
   1.183+		/* dubious stuff starts here */
   1.184+		lput(0L);
   1.185+		lput(0L);
   1.186+		lput(0L);
   1.187+		lput(0L);
   1.188+		lput(~0L);			/* gp value ?? */
   1.189+		break;
   1.190+	case 1:
   1.191+		lput(0x0183L);		/* magic and sections */
   1.192+		lput(0L);			/* time and date */
   1.193+		vlput(HEADR+textsize+datsize);
   1.194+		lput(symsize);			/* nsyms */
   1.195+		lput(0x54L|(7L<<16));		/* size of optional hdr and flags */
   1.196+		lput(0407|(0x101L<<16));	/* magic and version */
   1.197+		lput(-1);			/* pad for alignment */
   1.198+
   1.199+		vlput(textsize);		/* sizes */
   1.200+		vlput(datsize);
   1.201+		vlput(bsssize);
   1.202+		vlput(entryvalue());		/* va of entry */
   1.203+		vlput(INITTEXT);		/* va of base of text */
   1.204+		vlput(INITDAT);			/* va of base of data */
   1.205+		vlput(INITDAT+datsize);		/* va of base of bss */
   1.206+		lput(~0L);			/* gp reg mask */
   1.207+		/* dubious stuff starts here */
   1.208+		lput(lcsize);
   1.209+		lput(0L);
   1.210+		lput(0L);
   1.211+		lput(0L);
   1.212+		lput(~0L);			/* gp value ?? */
   1.213+		lput(0L);			/* complete mystery */
   1.214+		break;
   1.215+	case 2:
   1.216+		lputbe(0x84b);			/* magic */
   1.217+		lputbe(textsize);		/* sizes */
   1.218+		lputbe(datsize);
   1.219+		lputbe(bsssize);
   1.220+		lputbe(symsize);		/* nsyms */
   1.221+		lputbe(entryvalue());		/* va of entry */
   1.222+		lputbe(0L);
   1.223+		lputbe(lcsize);
   1.224+		break;
   1.225+	case 3:
   1.226+		/* ``headerless'' boot image -- magic no is a branch */
   1.227+		lput(0xc3e00007);		/* magic (branch) */
   1.228+		lputbe(textsize);		/* sizes */
   1.229+		lputbe(datsize);
   1.230+		lputbe(bsssize);
   1.231+		lputbe(symsize);		/* nsyms */
   1.232+		lputbe(entryvalue());		/* va of entry */
   1.233+		lputbe(0L);
   1.234+		lputbe(lcsize);
   1.235+		break;
   1.236+	}
   1.237+	cflush();
   1.238+}
   1.239+
   1.240+void
   1.241+lput(long l)
   1.242+{
   1.243+	LPUT(l);
   1.244+}
   1.245+
   1.246+void
   1.247+lputbe(long l)
   1.248+{
   1.249+	LPUTBE(l);
   1.250+}
   1.251+
   1.252+void
   1.253+vlput(vlong l)
   1.254+{
   1.255+	VLPUT(l);
   1.256+}
   1.257+
   1.258+void
   1.259+cflush(void)
   1.260+{
   1.261+	int n;
   1.262+
   1.263+	n = sizeof(buf.cbuf) - cbc;
   1.264+	if(n)
   1.265+		write(cout, buf.cbuf, n);
   1.266+	cbp = buf.cbuf;
   1.267+	cbc = sizeof(buf.cbuf);
   1.268+}
   1.269+
   1.270+void
   1.271+asmsym(void)
   1.272+{
   1.273+	Prog *p;
   1.274+	Auto *a;
   1.275+	Sym *s;
   1.276+	int h;
   1.277+
   1.278+	s = lookup("etext", 0);
   1.279+	if(s->type == STEXT)
   1.280+		putsymb(s->name, 'T', s->value, s->version);
   1.281+
   1.282+	for(h=0; h<NHASH; h++)
   1.283+		for(s=hash[h]; s!=S; s=s->link)
   1.284+			switch(s->type) {
   1.285+			case SCONST:
   1.286+				putsymb(s->name, 'D', s->value, s->version);
   1.287+				continue;
   1.288+
   1.289+			case SDATA:
   1.290+				putsymb(s->name, 'D', s->value+INITDAT, s->version);
   1.291+				continue;
   1.292+
   1.293+			case SBSS:
   1.294+				putsymb(s->name, 'B', s->value+INITDAT, s->version);
   1.295+				continue;
   1.296+
   1.297+			case SFILE:
   1.298+				putsymb(s->name, 'f', s->value, s->version);
   1.299+				continue;
   1.300+			}
   1.301+
   1.302+	for(p=textp; p!=P; p=p->cond) {
   1.303+		s = p->from.sym;
   1.304+		if(s->type != STEXT && s->type != SLEAF)
   1.305+			continue;
   1.306+
   1.307+		/* filenames first */
   1.308+		for(a=p->to.autom; a; a=a->link)
   1.309+			if(a->type == D_FILE)
   1.310+				putsymb(a->sym->name, 'z', a->offset, 0);
   1.311+			else
   1.312+			if(a->type == D_FILE1)
   1.313+				putsymb(a->sym->name, 'Z', a->offset, 0);
   1.314+
   1.315+		if(s->type == STEXT)
   1.316+			putsymb(s->name, 'T', s->value, s->version);
   1.317+		else
   1.318+			putsymb(s->name, 'L', s->value, s->version);
   1.319+
   1.320+		/* frame, auto and param after */
   1.321+		putsymb(".frame", 'm', p->to.offset+8, 0);
   1.322+		for(a=p->to.autom; a; a=a->link)
   1.323+			if(a->type == D_AUTO)
   1.324+				putsymb(a->sym->name, 'a', -a->offset, 0);
   1.325+			else
   1.326+			if(a->type == D_PARAM)
   1.327+				putsymb(a->sym->name, 'p', a->offset, 0);
   1.328+	}
   1.329+	if(debug['v'] || debug['n'])
   1.330+		Bprint(&bso, "symsize = %lud\n", symsize);
   1.331+	Bflush(&bso);
   1.332+}
   1.333+
   1.334+void
   1.335+putsymb(char *s, int t, long v, int ver)
   1.336+{
   1.337+	int i, f;
   1.338+
   1.339+	if(t == 'f')
   1.340+		s++;
   1.341+	LPUTBE(v);
   1.342+	if(ver)
   1.343+		t += 'a' - 'A';
   1.344+	CPUT(t+0x80);			/* 0x80 is variable length */
   1.345+
   1.346+	if(t == 'Z' || t == 'z') {
   1.347+		CPUT(s[0]);
   1.348+		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
   1.349+			CPUT(s[i]);
   1.350+			CPUT(s[i+1]);
   1.351+		}
   1.352+		CPUT(0);
   1.353+		CPUT(0);
   1.354+		i++;
   1.355+	}
   1.356+	else {
   1.357+		for(i=0; s[i]; i++)
   1.358+			CPUT(s[i]);
   1.359+		CPUT(0);
   1.360+	}
   1.361+	symsize += 4 + 1 + i + 1;
   1.362+
   1.363+	if(debug['n']) {
   1.364+		if(t == 'z' || t == 'Z') {
   1.365+			Bprint(&bso, "%c %.8lux ", t, v);
   1.366+			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
   1.367+				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
   1.368+				Bprint(&bso, "/%x", f);
   1.369+			}
   1.370+			Bprint(&bso, "\n");
   1.371+			return;
   1.372+		}
   1.373+		if(ver)
   1.374+			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
   1.375+		else
   1.376+			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
   1.377+	}
   1.378+}
   1.379+
   1.380+#define	MINLC	4
   1.381+void
   1.382+asmlc(void)
   1.383+{
   1.384+	long oldpc, oldlc;
   1.385+	Prog *p;
   1.386+	long v, s;
   1.387+
   1.388+	oldpc = INITTEXT;
   1.389+	oldlc = 0;
   1.390+	for(p = firstp; p != P; p = p->link) {
   1.391+		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
   1.392+			if(p->as == ATEXT)
   1.393+				curtext = p;
   1.394+			if(debug['L'])
   1.395+				Bprint(&bso, "%6lux %P\n",
   1.396+					p->pc, p);
   1.397+			continue;
   1.398+		}
   1.399+		if(debug['L'])
   1.400+			Bprint(&bso, "\t\t%6ld", lcsize);
   1.401+		v = (p->pc - oldpc) / MINLC;
   1.402+		while(v) {
   1.403+			s = 127;
   1.404+			if(v < 127)
   1.405+				s = v;
   1.406+			CPUT(s+128);	/* 129-255 +pc */
   1.407+			if(debug['L'])
   1.408+				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
   1.409+			v -= s;
   1.410+			lcsize++;
   1.411+		}
   1.412+		s = p->line - oldlc;
   1.413+		oldlc = p->line;
   1.414+		oldpc = p->pc + MINLC;
   1.415+		if(s > 64 || s < -64) {
   1.416+			CPUT(0);	/* 0 vv +lc */
   1.417+			CPUT(s>>24);
   1.418+			CPUT(s>>16);
   1.419+			CPUT(s>>8);
   1.420+			CPUT(s);
   1.421+			if(debug['L']) {
   1.422+				if(s > 0)
   1.423+					Bprint(&bso, " lc+%ld(%d,%ld)\n",
   1.424+						s, 0, s);
   1.425+				else
   1.426+					Bprint(&bso, " lc%ld(%d,%ld)\n",
   1.427+						s, 0, s);
   1.428+				Bprint(&bso, "%6lux %P\n",
   1.429+					p->pc, p);
   1.430+			}
   1.431+			lcsize += 5;
   1.432+			continue;
   1.433+		}
   1.434+		if(s > 0) {
   1.435+			CPUT(0+s);	/* 1-64 +lc */
   1.436+			if(debug['L']) {
   1.437+				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
   1.438+				Bprint(&bso, "%6lux %P\n",
   1.439+					p->pc, p);
   1.440+			}
   1.441+		} else {
   1.442+			CPUT(64-s);	/* 65-128 -lc */
   1.443+			if(debug['L']) {
   1.444+				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
   1.445+				Bprint(&bso, "%6lux %P\n",
   1.446+					p->pc, p);
   1.447+			}
   1.448+		}
   1.449+		lcsize++;
   1.450+	}
   1.451+	while(lcsize & 1) {
   1.452+		s = 129;
   1.453+		CPUT(s);
   1.454+		lcsize++;
   1.455+	}
   1.456+	if(debug['v'] || debug['L'])
   1.457+		Bprint(&bso, "lcsize = %ld\n", lcsize);
   1.458+	Bflush(&bso);
   1.459+}
   1.460+
   1.461+void
   1.462+datblk(long s, long n)
   1.463+{
   1.464+	Prog *p;
   1.465+	char *cast;
   1.466+	long l, fl, j, d;
   1.467+	int i, c;
   1.468+
   1.469+	memset(buf.dbuf, 0, n+100);
   1.470+	for(p = datap; p != P; p = p->link) {
   1.471+		curp = p;
   1.472+		l = p->from.sym->value + p->from.offset - s;
   1.473+		c = p->reg;
   1.474+		i = 0;
   1.475+		if(l < 0) {
   1.476+			if(l+c <= 0)
   1.477+				continue;
   1.478+			while(l < 0) {
   1.479+				l++;
   1.480+				i++;
   1.481+			}
   1.482+		}
   1.483+		if(l >= n)
   1.484+			continue;
   1.485+		if(p->as != AINIT && p->as != ADYNT) {
   1.486+			for(j=l+(c-i)-1; j>=l; j--)
   1.487+				if(buf.dbuf[j]) {
   1.488+					print("%P\n", p);
   1.489+					diag("multiple initialization");
   1.490+					break;
   1.491+				}
   1.492+		}
   1.493+		switch(p->to.type) {
   1.494+		default:
   1.495+			diag("unknown mode in initialization\n%P", p);
   1.496+			break;
   1.497+
   1.498+		case D_FCONST:
   1.499+			switch(c) {
   1.500+			default:
   1.501+			case 4:
   1.502+				fl = ieeedtof(p->to.ieee);
   1.503+				cast = (char*)&fl;
   1.504+				for(; i<c; i++) {
   1.505+					buf.dbuf[l] = cast[fnuxi8[i]];
   1.506+					l++;
   1.507+				}
   1.508+				break;
   1.509+			case 8:
   1.510+				cast = (char*)p->to.ieee;
   1.511+				for(; i<c; i++) {
   1.512+					buf.dbuf[l] = cast[fnuxi8[i]];
   1.513+					l++;
   1.514+				}
   1.515+				break;
   1.516+			}
   1.517+			break;
   1.518+
   1.519+		case D_SCONST:
   1.520+			for(; i<c; i++) {
   1.521+				buf.dbuf[l] = p->to.sval[i];
   1.522+				l++;
   1.523+			}
   1.524+			break;
   1.525+
   1.526+		case D_CONST:
   1.527+			d = p->to.offset;
   1.528+			if(p->to.sym) {
   1.529+				if(p->to.sym->type == STEXT ||
   1.530+				   p->to.sym->type == SLEAF)
   1.531+					d += p->to.sym->value;
   1.532+				if(p->to.sym->type == SDATA)
   1.533+					d += p->to.sym->value + INITDAT;
   1.534+				if(p->to.sym->type == SBSS)
   1.535+					d += p->to.sym->value + INITDAT;
   1.536+			}
   1.537+			cast = (char*)&d;
   1.538+			switch(c) {
   1.539+			default:
   1.540+				diag("bad nuxi %d %d\n%P", c, i, curp);
   1.541+				break;
   1.542+			case 1:
   1.543+				for(; i<c; i++) {
   1.544+					buf.dbuf[l] = cast[inuxi1[i]];
   1.545+					l++;
   1.546+				}
   1.547+				break;
   1.548+			case 2:
   1.549+				for(; i<c; i++) {
   1.550+					buf.dbuf[l] = cast[inuxi2[i]];
   1.551+					l++;
   1.552+				}
   1.553+				break;
   1.554+			case 4:
   1.555+				for(; i<c; i++) {
   1.556+					buf.dbuf[l] = cast[inuxi4[i]];
   1.557+					l++;
   1.558+				}
   1.559+				break;
   1.560+			case 8:
   1.561+				for(; i<4; i++) {
   1.562+					buf.dbuf[l] = cast[inuxi4[i]];
   1.563+					l++;
   1.564+				}
   1.565+				d = p->to.offset >> 32;
   1.566+				for(; i<c; i++) {
   1.567+					buf.dbuf[l] = cast[inuxi4[i-4]];
   1.568+					l++;
   1.569+				}
   1.570+				break;
   1.571+			}
   1.572+			break;
   1.573+		}
   1.574+	}
   1.575+	write(cout, buf.dbuf, n);
   1.576+}
   1.577+
   1.578+#define	OP_RRR(op,r1,r2,r3)\
   1.579+	(op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|((r3)&31L))
   1.580+#define	OP_IRR(op,i,r2,r3)\
   1.581+	(op|(((i)&255L)<<13)|0x1000|(((r2)&31L)<<21)|((r3)&31L))
   1.582+#define	OP_MEM(op,d,r1,r2)\
   1.583+	(op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|((d)&0xffff))
   1.584+#define OP_BR(op,d,r1)\
   1.585+	(op|((d)&0x1fffff)|(((r1)&31L)<<21))
   1.586+
   1.587+int
   1.588+asmout(Prog *p, Optab *o)
   1.589+{
   1.590+	long o1, o2, o3, o4, o5, o6;
   1.591+	vlong v;
   1.592+	int r, a;
   1.593+
   1.594+	o1 = 0;
   1.595+	o2 = 0;
   1.596+	o3 = 0;
   1.597+	o4 = 0;
   1.598+	o5 = 0;
   1.599+	o6 = 0;
   1.600+	switch(o->type) {
   1.601+	default:
   1.602+		diag("unknown type %d", o->type);
   1.603+		if(!debug['a'])
   1.604+			prasm(p);
   1.605+		break;
   1.606+
   1.607+	case 0:		/* pseudo ops */
   1.608+		break;
   1.609+
   1.610+	case 1:		/* register-register moves */
   1.611+		if(p->as == AMOVB || p->as == AMOVW)		/* noop should rewrite */
   1.612+			diag("forbidden SEX: %P", p);
   1.613+		if(p->as == AMOVBU || p->as == AMOVWU) {
   1.614+			v = 1;
   1.615+			if (p->as == AMOVWU)
   1.616+				v = 3;
   1.617+			o1 = OP_IRR(opcode(AZAPNOT), v, p->from.reg, p->to.reg);
   1.618+		}
   1.619+		else {
   1.620+			a = AOR;
   1.621+			if(p->as == AMOVL)
   1.622+				a = AADDL;
   1.623+			if(p->as == AMOVLU)
   1.624+				a = AEXTLL;
   1.625+			o1 = OP_RRR(opcode(a), REGZERO, p->from.reg, p->to.reg);
   1.626+		}
   1.627+		break;
   1.628+
   1.629+	case 2:		/* <operate> r1,[r2],r3 */
   1.630+		r = p->reg;
   1.631+		if(r == NREG)
   1.632+			r = p->to.reg;
   1.633+		o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
   1.634+		break;
   1.635+
   1.636+	case 3:		/* <operate> $n,[r2],r3 */
   1.637+		v = regoff(&p->from);
   1.638+		r = p->reg;
   1.639+		if(r == NREG)
   1.640+			r = p->to.reg;
   1.641+		o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
   1.642+		break;
   1.643+
   1.644+	case 4:		/* beq r1,sbra */
   1.645+		if(p->cond == P)
   1.646+			v = -4 >> 2;
   1.647+		else
   1.648+			v = (p->cond->pc - pc-4) >> 2;
   1.649+		o1 = OP_BR(opcode(p->as), v, p->from.reg);
   1.650+		break;
   1.651+
   1.652+	case 5:		/* jmp [r1],0(r2) */
   1.653+		r = p->reg;
   1.654+		a = p->as;
   1.655+		if(r == NREG) {
   1.656+			r = o->param;
   1.657+/*			if(a == AJMP && p->to.reg == REGLINK)
   1.658+				a = ARET; /* this breaks the kernel -- maybe we need to clear prediction stack on each context switch... */
   1.659+		}
   1.660+		o1 = OP_MEM(opcode(a), 0, p->to.reg, r);
   1.661+		break;
   1.662+
   1.663+	case 6:		/* movq $n,r1 and movq $soreg,r1 */
   1.664+		r = p->from.reg;
   1.665+		if(r == NREG)
   1.666+			r = o->param;
   1.667+		v = regoff(&p->from);
   1.668+		o1 = OP_MEM(opcode(AMOVA), v, r, p->to.reg);
   1.669+		break;
   1.670+
   1.671+	case 7:		/* movbu r1, r2 */
   1.672+		v = 1;
   1.673+		if (p->as == AMOVWU)
   1.674+			v = 3;
   1.675+		o1 = OP_IRR(opcode(AZAPNOT), v, p->from.reg, p->to.reg);
   1.676+		break;
   1.677+
   1.678+	case 8:		/* mov r, soreg ==> stq o(r) */
   1.679+		r = p->to.reg;
   1.680+		if(r == NREG)
   1.681+			r = o->param;
   1.682+		v = regoff(&p->to);
   1.683+		if (p->as == AMOVQ || p->as == AMOVT)
   1.684+			if ((r == REGSP || r == REGSB) && (v&7) != 0)
   1.685+				diag("bad alignment: %P", p);
   1.686+		o1 = OP_MEM(opcode(p->as+AEND), v, r, p->from.reg);
   1.687+		break;
   1.688+
   1.689+	case 9:		/* mov soreg, r ==> ldq o(r) */
   1.690+		r = p->from.reg;
   1.691+		if(r == NREG)
   1.692+			r = o->param;
   1.693+		v = regoff(&p->from);
   1.694+		if (p->as == AMOVQ || p->as == AMOVT)
   1.695+			if ((r == REGSP || r == REGSB) && (v&7) != 0)
   1.696+				diag("bad alignment: %P", p);
   1.697+		o1 = OP_MEM(opcode(p->as), v, r, p->to.reg);
   1.698+		break;
   1.699+
   1.700+	case 10:	/* movb r1,r2 */
   1.701+		v = 64 - 8;
   1.702+		if (p->as == AMOVW)
   1.703+			v = 64 - 16;
   1.704+		o1 = OP_IRR(opcode(ASLLQ), v, p->from.reg, p->to.reg);
   1.705+		o2 = OP_IRR(opcode(ASRAQ), v, p->to.reg, p->to.reg);
   1.706+		break;
   1.707+
   1.708+	case 11:	/* jmp lbra */
   1.709+		if(p->cond == P)
   1.710+			v = -4 >> 2;
   1.711+		else
   1.712+			v = (p->cond->pc - pc-4) >> 2;
   1.713+		a = ABR;
   1.714+		r = REGZERO;
   1.715+		if (p->as == AJSR) {
   1.716+			a = ABSR;
   1.717+			r = REGLINK;
   1.718+		}
   1.719+		o1 = OP_BR(opcode(a), v, r);
   1.720+		break;
   1.721+
   1.722+	case 12:	/* addq $n,[r2],r3 ==> lda */
   1.723+		v = regoff(&p->from);
   1.724+		if (p->as == ASUBQ)
   1.725+			v = -v;
   1.726+		r = p->reg;
   1.727+		if(r == NREG)
   1.728+			r = p->to.reg;
   1.729+		o1 = OP_MEM(opcode(AMOVA), v, r, p->to.reg);
   1.730+		break;
   1.731+
   1.732+	case 13:	/* <op> $scon,[r2],r3 */
   1.733+		v = regoff(&p->from);
   1.734+		if(p->to.reg == REGTMP || p->reg == REGTMP)
   1.735+			diag("cant synthesize large constant\n%P", p);
   1.736+		r = p->reg;
   1.737+		if(r == NREG)
   1.738+			r = p->to.reg;
   1.739+		o1 = OP_MEM(opcode(AMOVA), v, REGZERO, REGTMP);
   1.740+		o2 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
   1.741+		break;
   1.742+
   1.743+	case 14:	/* <op> $lcon,[r2],r3 */
   1.744+		v = regoff(&p->from);
   1.745+		if(v & 0x8000)
   1.746+			v += 0x10000;
   1.747+		if(p->to.reg == REGTMP || p->reg == REGTMP)
   1.748+			diag("cant synthesize large constant\n%P", p);
   1.749+		r = p->reg;
   1.750+		if(r == NREG)
   1.751+			r = p->to.reg;
   1.752+		o1 = OP_MEM(opcode(AMOVA), v, REGZERO, REGTMP);
   1.753+		o2 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, REGTMP);
   1.754+		o3 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
   1.755+		break;
   1.756+
   1.757+	case 15:	/* mov $lcon,r1 */
   1.758+		v = regoff(&p->from);
   1.759+		if(v & 0x8000)
   1.760+			v += 0x10000;
   1.761+		o1 = OP_MEM(opcode(AMOVA), v, o->param, REGTMP);
   1.762+		o2 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, p->to.reg);
   1.763+		break;
   1.764+
   1.765+	case 16:	/* mov $qcon,r1 */
   1.766+		v = regoff(&p->from);
   1.767+		if(v & 0x8000)
   1.768+			v += 0x10000;
   1.769+		if((v>>31)&1)
   1.770+			v += (1LL<<32);
   1.771+		if((v>>47)&1)
   1.772+			v += (1LL<<48);
   1.773+		o1 = OP_MEM(opcode(AMOVA), v>>32, o->param, REGTMP);
   1.774+		o2 = OP_MEM(opcode(AMOVAH), v>>48, REGTMP, REGTMP);
   1.775+		o3 = OP_IRR(opcode(ASLLQ), 32, REGTMP, REGTMP);
   1.776+		o4 = OP_MEM(opcode(AMOVA), v, REGTMP, REGTMP);
   1.777+		o5 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, p->to.reg);
   1.778+		break;
   1.779+
   1.780+	case 17:	/* mov f1,f2 ==> fcpys f1,f1,f2 */
   1.781+		o1 = OP_RRR(opcode(ACPYS), p->from.reg, p->from.reg, p->to.reg);
   1.782+		break;
   1.783+
   1.784+	case 18:	/* call_pal imm */
   1.785+		v = regoff(&p->from);
   1.786+		o1 = OP_MEM(opcode(ACALL_PAL), v, 0, 0);
   1.787+		break;
   1.788+
   1.789+	case 19:	/* mov r, loreg ==> ldah,stq */
   1.790+		r = p->to.reg;
   1.791+		if(r == NREG)
   1.792+			r = o->param;
   1.793+		v = regoff(&p->to);
   1.794+		if (p->as == AMOVQ || p->as == AMOVT)
   1.795+			if ((r == REGSP || r == REGSB) && (v&7) != 0)
   1.796+				diag("bad alignment: %P", p);
   1.797+		if(v & 0x8000)
   1.798+			v += 0x10000;
   1.799+		o1 = OP_MEM(opcode(AMOVAH), v>>16, r, REGTMP);
   1.800+		o2 = OP_MEM(opcode(p->as+AEND), v, REGTMP, p->from.reg);
   1.801+		break;
   1.802+
   1.803+	case 20:	/* mov loreg, r ==> ldah,ldq */
   1.804+		r = p->from.reg;
   1.805+		if(r == NREG)
   1.806+			r = o->param;
   1.807+		v = regoff(&p->from);
   1.808+		if (p->as == AMOVQ || p->as == AMOVT)
   1.809+			if ((r == REGSP || r == REGSB) && (v&7) != 0)
   1.810+				diag("bad alignment: %P", p);
   1.811+		if(v & 0x8000)
   1.812+			v += 0x10000;
   1.813+		o1 = OP_MEM(opcode(AMOVAH), v>>16, r, REGTMP);
   1.814+		o2 = OP_MEM(opcode(p->as), v, REGTMP, p->to.reg);
   1.815+		break;
   1.816+
   1.817+#ifdef	NEVER
   1.818+	case 21:	/* mov r1,$qoreg */
   1.819+		r = p->to.reg;
   1.820+		if(r == NREG)
   1.821+			r = o->param;
   1.822+		v = regoff(&p->to);
   1.823+		if(v & 0x8000)
   1.824+			v += 0x10000;
   1.825+		if((v>>31)&1)
   1.826+			v += (1LL<<32);
   1.827+		if((v>>47)&1)
   1.828+			v += (1LL<<48);
   1.829+		o1 = OP_MEM(opcode(AMOVA), v>>32, r, REGTMP);
   1.830+		o2 = OP_MEM(opcode(AMOVAH), v>>48, REGTMP, REGTMP);
   1.831+		o3 = OP_IRR(opcode(ASLLQ), 32, REGTMP, REGTMP);
   1.832+		o4 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, REGTMP);
   1.833+		o5 = OP_MEM(opcode(p->as+AEND), v, REGTMP, p->from.reg);
   1.834+		break;
   1.835+
   1.836+	case 22:	/* mov $qoreg,r1 */
   1.837+		r = p->from.reg;
   1.838+		if(r == NREG)
   1.839+			r = o->param;
   1.840+		v = regoff(&p->from);
   1.841+		if(v & 0x8000)
   1.842+			v += 0x10000;
   1.843+		if((v>>31)&1)
   1.844+			v += (1LL<<32);
   1.845+		if((v>>47)&1)
   1.846+			v += (1LL<<48);
   1.847+		o1 = OP_MEM(opcode(AMOVA), v>>32, r, REGTMP);
   1.848+		o2 = OP_MEM(opcode(AMOVAH), v>>48, REGTMP, REGTMP);
   1.849+		o3 = OP_IRR(opcode(ASLLQ), 32, REGTMP, REGTMP);
   1.850+		o4 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, REGTMP);
   1.851+		o5 = OP_MEM(opcode(p->as), v, REGTMP, p->to.reg);
   1.852+		break;
   1.853+#endif
   1.854+
   1.855+	case 23:	/* <op> $qcon,r1 */
   1.856+		if(p->to.reg == REGTMP || p->reg == REGTMP)
   1.857+			diag("cant synthesize large constant\n%P", p);
   1.858+		v = regoff(&p->from);
   1.859+		r = p->reg;
   1.860+		if(r == NREG)
   1.861+			r = p->to.reg;
   1.862+		if(v & 0x8000)
   1.863+			v += 0x10000;
   1.864+		if((v>>31)&1)
   1.865+			v += (1LL<<32);
   1.866+		if((v>>47)&1)
   1.867+			v += (1LL<<48);
   1.868+		o1 = OP_MEM(opcode(AMOVA), v>>32, REGZERO, REGTMP);
   1.869+		o2 = OP_MEM(opcode(AMOVAH), v>>48, REGTMP, REGTMP);
   1.870+		o3 = OP_IRR(opcode(ASLLQ), 32, REGTMP, REGTMP);
   1.871+		o4 = OP_MEM(opcode(AMOVA), v, REGTMP, REGTMP);
   1.872+		o5 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, REGTMP);
   1.873+		o6 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
   1.874+		break;
   1.875+
   1.876+	case 24:	/* movq Fn, FPCR */
   1.877+		r = p->from.reg;
   1.878+		o1 = OP_RRR(opcode(AADDT+AEND), r, r, r);
   1.879+		break;
   1.880+
   1.881+	case 25:	/* movq FPCR, Fn */
   1.882+		r = p->to.reg;
   1.883+		o1 = OP_RRR(opcode(AADDS+AEND), r, r, r);
   1.884+		break;
   1.885+
   1.886+	case 26:	/* movq Rn, C_PREG */
   1.887+		r = p->from.reg;
   1.888+		o1 = OP_RRR(opcode(ASUBQ+AEND), r, r, 0) | p->to.reg & 255;
   1.889+		break;
   1.890+
   1.891+	case 27:	/* movq C_PREG, Rn */
   1.892+		r = p->to.reg;
   1.893+		o1 = OP_RRR(opcode(AADDQ+AEND), r, r, 0) | p->from.reg & 255;
   1.894+		break;
   1.895+
   1.896+	case 28:	/* cvttq r1,r3 */
   1.897+		r = p->from.reg;
   1.898+		o1 = OP_RRR(opcode(p->as), r, REGZERO, p->to.reg);
   1.899+		break;
   1.900+
   1.901+	case 29:	/* movq pcc, rpcc -> Rn */
   1.902+		o1 = OP_MEM(opcode(ARPCC), 0, REGZERO, p->to.reg);
   1.903+		break;
   1.904+
   1.905+	case 30:	/* rei/mb/trapb */
   1.906+		o1 = OP_MEM(opcode(p->as), 0, REGZERO, REGZERO);
   1.907+		break;
   1.908+
   1.909+	case 31:	/* fetch (Rn) */
   1.910+		o1 = OP_MEM(opcode(p->as), 0, REGZERO, p->from.reg);
   1.911+		break;
   1.912+
   1.913+	case 32:	/* movqp r, soreg ==> stqp o(r) */
   1.914+		r = p->to.reg;
   1.915+		if(r == NREG)
   1.916+			r = o->param;
   1.917+		v = regoff(&p->to);
   1.918+		if (v < -0x800 || v >= 0x800)
   1.919+			diag("physical store out of range\n%P", p);
   1.920+		v &= 0xfff;
   1.921+		o1 = OP_MEM(opcode(p->as+AEND), v, r, p->from.reg);
   1.922+		break;
   1.923+
   1.924+	case 33:	/* movqp soreg, r ==> ldqp o(r) */
   1.925+		r = p->from.reg;
   1.926+		if(r == NREG)
   1.927+			r = o->param;
   1.928+		v = regoff(&p->from);
   1.929+		if (v < -0x800 || v >= 0x800)
   1.930+			diag("physical load out of range\n%P", p);
   1.931+		v &= 0xfff;
   1.932+		o1 = OP_MEM(opcode(p->as), v, r, p->to.reg);
   1.933+		break;
   1.934+
   1.935+	case 34:	/* <operate> $-n,[r2],r3 */
   1.936+		v = regoff(&p->from);
   1.937+		r = p->reg;
   1.938+		if(r == NREG)
   1.939+			r = p->to.reg;
   1.940+		switch (a = p->as) {
   1.941+		case AAND:
   1.942+			a = AANDNOT;
   1.943+			break;
   1.944+		case AANDNOT:
   1.945+			a = AAND;
   1.946+			break;
   1.947+		case AOR:
   1.948+			a = AORNOT;
   1.949+			break;
   1.950+		case AORNOT:
   1.951+			a = AOR;
   1.952+			break;
   1.953+		case AXOR:
   1.954+			a = AXORNOT;
   1.955+			break;
   1.956+		case AXORNOT:
   1.957+			a = AXOR;
   1.958+			break;
   1.959+		default:
   1.960+			diag("bad in NCON case: %P", p);
   1.961+		}
   1.962+		v = ~v;
   1.963+		o1 = OP_IRR(opcode(a), v, r, p->to.reg);
   1.964+		break;
   1.965+
   1.966+	case 40:	/* word */
   1.967+		o1 = regoff(&p->to);
   1.968+		break;
   1.969+
   1.970+	}
   1.971+	switch(o->size) {
   1.972+	default:
   1.973+		if(debug['a'])
   1.974+			Bprint(&bso, " %.8lux:\t\t%P\n", p->pc, p);
   1.975+		break;
   1.976+	case 4:
   1.977+		if(debug['a'])
   1.978+			Bprint(&bso, " %.8lux: %.8lux\t%P\n", p->pc, o1, p);
   1.979+		LPUT(o1);
   1.980+		break;
   1.981+	case 8:
   1.982+		if(debug['a'])
   1.983+			Bprint(&bso, " %.8lux: %.8lux %.8lux %P\n", p->pc, o1, o2, p);
   1.984+		LPUT(o1);
   1.985+		LPUT(o2);
   1.986+		break;
   1.987+	case 12:
   1.988+		if(debug['a'])
   1.989+			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %P\n", p->pc, o1, o2, o3, p);
   1.990+		LPUT(o1);
   1.991+		LPUT(o2);
   1.992+		LPUT(o3);
   1.993+		break;
   1.994+	case 16:
   1.995+		if(debug['a'])
   1.996+			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %P\n",
   1.997+				p->pc, o1, o2, o3, o4, p);
   1.998+		LPUT(o1);
   1.999+		LPUT(o2);
  1.1000+		LPUT(o3);
  1.1001+		LPUT(o4);
  1.1002+		break;
  1.1003+	case 20:
  1.1004+		if(debug['a'])
  1.1005+			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %P\n",
  1.1006+				p->pc, o1, o2, o3, o4, o5, p);
  1.1007+		LPUT(o1);
  1.1008+		LPUT(o2);
  1.1009+		LPUT(o3);
  1.1010+		LPUT(o4);
  1.1011+		LPUT(o5);
  1.1012+		break;
  1.1013+	case 24:
  1.1014+		if(debug['a'])
  1.1015+			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %P\n",
  1.1016+				p->pc, o1, o2, o3, o4, o5, o6, p);
  1.1017+		LPUT(o1);
  1.1018+		LPUT(o2);
  1.1019+		LPUT(o3);
  1.1020+		LPUT(o4);
  1.1021+		LPUT(o5);
  1.1022+		LPUT(o6);
  1.1023+		break;
  1.1024+	}
  1.1025+	return 0;
  1.1026+}
  1.1027+
  1.1028+#define	OP(x,y)	(((x)<<26)|((y)<<5))
  1.1029+#define	FP(x)	OP(22, (x)|0xc0)	/* note: this sets round/trap modes (dynamic, software?). not used for cvtxx? */
  1.1030+#define	FP2(x)	OP(22, (x) /*|0x080*/)	/* note: this sets round/trap modes (chopped, software?). used for cvtxx? */
  1.1031+#define	FP3(x)	OP(22, (x)|0x080)	/* note: this sets round/trap modes (dynamic, software?). not used for cvtxx? */
  1.1032+
  1.1033+long
  1.1034+opcode(int a)
  1.1035+{
  1.1036+	switch (a) {
  1.1037+	/* loads */
  1.1038+	case AMOVB:		/* misnomer; pretend it's ok for now */
  1.1039+diag("opcode(AMOVB)");
  1.1040+	case AMOVBU:		return OP(10, 0);	/* v 3 */
  1.1041+	case AMOVW:		/* misnomer; pretend it's ok for now */
  1.1042+diag("opcode(AMOVW)");
  1.1043+	case AMOVWU:		return OP(12, 0);	/* v 3 */
  1.1044+	case AMOVL:		return OP(40, 0);
  1.1045+	case AMOVQ:		return OP(41, 0);
  1.1046+	case AMOVQU:		return OP(11, 0);
  1.1047+	case AMOVS:		return OP(34, 0);
  1.1048+	case AMOVT:		return OP(35, 0);
  1.1049+
  1.1050+	/* stores */
  1.1051+	case AMOVB+AEND:		/* misnomer; pretend it's ok for now */
  1.1052+	case AMOVBU+AEND:	return OP(14, 0);	/* v 3 */
  1.1053+	case AMOVW+AEND:	/* misnomer; pretend it's ok for now */
  1.1054+	case AMOVWU+AEND:	return OP(13, 0);	/* v 3 */
  1.1055+	case AMOVL+AEND:	return OP(44, 0);
  1.1056+	case AMOVQ+AEND:	return OP(45, 0);
  1.1057+	case AMOVQU+AEND:	return OP(15, 0);
  1.1058+	case AMOVS+AEND:	return OP(38, 0);
  1.1059+	case AMOVT+AEND:	return OP(39, 0);
  1.1060+
  1.1061+	/* physical */
  1.1062+	case AMOVLP+AEND:	return OP(31, 0)|0x8000;
  1.1063+	case AMOVQP+AEND:	return OP(31, 0)|0x9000;
  1.1064+	case AMOVLP:		return OP(27, 0)|0x8000;
  1.1065+	case AMOVQP:		return OP(27, 0)|0x9000;
  1.1066+
  1.1067+	/* load address */
  1.1068+	case AMOVA:		return OP(8, 0);
  1.1069+	case AMOVAH:		return OP(9, 0);
  1.1070+
  1.1071+	/* locking */
  1.1072+	case AMOVLL:		return OP(42, 0);	/* load locked */
  1.1073+	case AMOVQL:		return OP(43, 0);	/* load locked */
  1.1074+	case AMOVLC+AEND:	return OP(46, 0);	/* store cond */
  1.1075+	case AMOVQC+AEND:	return OP(47, 0);	/* store cond */
  1.1076+
  1.1077+	case AADDL:		return OP(16, 0);
  1.1078+	case AADDLV:		return OP(16, 64);
  1.1079+	case AADDQ:		return OP(16, 32);
  1.1080+	case AADDQV:		return OP(16, 96);
  1.1081+	case AS4ADDL:		return OP(16, 2);
  1.1082+	case AS4ADDQ:		return OP(16, 34);
  1.1083+	case AS8ADDL:		return OP(16, 18);
  1.1084+	case AS8ADDQ:		return OP(16, 50);
  1.1085+	case AS4SUBL:		return OP(16, 11);
  1.1086+	case AS4SUBQ:		return OP(16, 43);
  1.1087+	case AS8SUBL:		return OP(16, 27);
  1.1088+	case AS8SUBQ:		return OP(16, 59);
  1.1089+	case ASUBL:		return OP(16, 9);
  1.1090+	case ASUBLV:		return OP(16, 73);
  1.1091+	case ASUBQ:		return OP(16, 41);
  1.1092+	case ASUBQV:		return OP(16, 105);
  1.1093+	case ACMPEQ:		return OP(16, 45);
  1.1094+	case ACMPGT:		return OP(16, 77);
  1.1095+	case ACMPGE:		return OP(16, 109);
  1.1096+	case ACMPUGT:		return OP(16, 29);
  1.1097+	case ACMPUGE:		return OP(16, 61);
  1.1098+	case ACMPBLE:		return OP(16, 15);
  1.1099+
  1.1100+	case AAND:		return OP(17, 0);
  1.1101+	case AANDNOT:		return OP(17, 8);
  1.1102+	case AOR:		return OP(17, 32);
  1.1103+	case AORNOT:		return OP(17, 40);
  1.1104+	case AXOR:		return OP(17, 64);
  1.1105+	case AXORNOT:		return OP(17, 72);
  1.1106+
  1.1107+	case ACMOVEQ:		return OP(17, 36);
  1.1108+	case ACMOVNE:		return OP(17, 38);
  1.1109+	case ACMOVLT:		return OP(17, 68);
  1.1110+	case ACMOVGE:		return OP(17, 70);
  1.1111+	case ACMOVLE:		return OP(17, 100);
  1.1112+	case ACMOVGT:		return OP(17, 102);
  1.1113+	case ACMOVLBS:		return OP(17, 20);
  1.1114+	case ACMOVLBC:		return OP(17, 22);
  1.1115+
  1.1116+	case AMULL:		return OP(19, 0);
  1.1117+	case AMULQ:		return OP(19, 32);
  1.1118+	case AMULLV:		return OP(19, 64);
  1.1119+	case AMULQV:		return OP(19, 96);
  1.1120+	case AUMULH:		return OP(19, 48);
  1.1121+
  1.1122+	case ASLLQ:		return OP(18, 57);
  1.1123+	case ASRLQ:		return OP(18, 52);
  1.1124+	case ASRAQ:		return OP(18, 60);
  1.1125+
  1.1126+	case AEXTBL:		return OP(18, 6);
  1.1127+	case AEXTWL:		return OP(18, 22);
  1.1128+	case AEXTLL:		return OP(18, 38);
  1.1129+	case AEXTQL:		return OP(18, 54);
  1.1130+	case AEXTWH:		return OP(18, 90);
  1.1131+	case AEXTLH:		return OP(18, 106);
  1.1132+	case AEXTQH:		return OP(18, 122);
  1.1133+
  1.1134+	case AINSBL:		return OP(18, 11);
  1.1135+	case AINSWL:		return OP(18, 27);
  1.1136+	case AINSLL:		return OP(18, 43);
  1.1137+	case AINSQL:		return OP(18, 59);
  1.1138+	case AINSWH:		return OP(18, 87);
  1.1139+	case AINSLH:		return OP(18, 103);
  1.1140+	case AINSQH:		return OP(18, 119);
  1.1141+
  1.1142+	case AMSKBL:		return OP(18, 2);
  1.1143+	case AMSKWL:		return OP(18, 18);
  1.1144+	case AMSKLL:		return OP(18, 34);
  1.1145+	case AMSKQL:		return OP(18, 50);
  1.1146+	case AMSKWH:		return OP(18, 82);
  1.1147+	case AMSKLH:		return OP(18, 98);
  1.1148+	case AMSKQH:		return OP(18, 114);
  1.1149+
  1.1150+	case AZAP:		return OP(18, 48);
  1.1151+	case AZAPNOT:		return OP(18, 49);
  1.1152+
  1.1153+	case AJMP:		return OP(26, 0);
  1.1154+	case AJSR:		return OP(26, 512);
  1.1155+	case ARET:		return OP(26, 1024);
  1.1156+
  1.1157+	case ABR:		return OP(48, 0);
  1.1158+	case ABSR:		return OP(52, 0);
  1.1159+
  1.1160+	case ABEQ:		return OP(57, 0);
  1.1161+	case ABNE:		return OP(61, 0);
  1.1162+	case ABLT:		return OP(58, 0);
  1.1163+	case ABGE:		return OP(62, 0);
  1.1164+	case ABLE:		return OP(59, 0);
  1.1165+	case ABGT:		return OP(63, 0);
  1.1166+	case ABLBC:		return OP(56, 0);
  1.1167+	case ABLBS:		return OP(60, 0);
  1.1168+
  1.1169+	case AFBEQ:		return OP(49, 0);
  1.1170+	case AFBNE:		return OP(53, 0);
  1.1171+	case AFBLT:		return OP(50, 0);
  1.1172+	case AFBGE:		return OP(54, 0);
  1.1173+	case AFBLE:		return OP(51, 0);
  1.1174+	case AFBGT:		return OP(55, 0);
  1.1175+
  1.1176+	case ATRAPB:		return OP(24, 0);
  1.1177+	case AMB:		return OP(24, 0x200);
  1.1178+	case AFETCH:		return OP(24, 0x400);
  1.1179+	case AFETCHM:		return OP(24, 0x500);
  1.1180+	case ARPCC:		return OP(24, 0x600);
  1.1181+
  1.1182+	case ACPYS:		return OP(23, 32);
  1.1183+	case ACPYSN:		return OP(23, 33);
  1.1184+	case ACPYSE:		return OP(23, 34);
  1.1185+	case AADDS+AEND:	return OP(23, 37);	/* MF_FPCR */
  1.1186+	case AADDT+AEND:	return OP(23, 36);	/* MT_FPCR */
  1.1187+	case ACVTLQ:		return OP(23, 16);
  1.1188+	case ACVTQL:		return OP(23, 48);	/* XXX trap mode */
  1.1189+	case AFCMOVEQ:		return OP(23, 42);
  1.1190+	case AFCMOVNE:		return OP(23, 43);
  1.1191+	case AFCMOVLT:		return OP(23, 44);
  1.1192+	case AFCMOVGE:		return OP(23, 45);
  1.1193+	case AFCMOVLE:		return OP(23, 46);
  1.1194+	case AFCMOVGT:		return OP(23, 47);
  1.1195+
  1.1196+	case AADDS:		return FP(0);
  1.1197+	case AADDT:		return FP(32);
  1.1198+	case ACMPTEQ:		return FP3(37);
  1.1199+	case ACMPTGT:		return FP3(38);
  1.1200+	case ACMPTGE:		return FP3(39);
  1.1201+	case ACMPTUN:		return FP3(36);
  1.1202+
  1.1203+	case ACVTQS:		return FP2(60);
  1.1204+	case ACVTQT:		return FP2(62);
  1.1205+	case ACVTTS:		return FP2(44);
  1.1206+	case ACVTTQ:		return FP2(47);
  1.1207+
  1.1208+	case ADIVS:		return FP(3);
  1.1209+	case ADIVT:		return FP(35);
  1.1210+	case AMULS:		return FP(2);
  1.1211+	case AMULT:		return FP(34);
  1.1212+	case ASUBS:		return FP(1);
  1.1213+	case ASUBT:		return FP(33);
  1.1214+
  1.1215+	case ACALL_PAL:		return 0;
  1.1216+	case AREI:		return OP(30, 0x400);	/* HW_REI */
  1.1217+
  1.1218+	case AADDQ+AEND:	return OP(25,0);	/* HW_MFPR */
  1.1219+	case ASUBQ+AEND:	return OP(29,0);	/* HW_MTPR */
  1.1220+	}
  1.1221+	diag("bad op %A(%d)", a, a);
  1.1222+	return 0;
  1.1223+}
  1.1224+