xref: /inferno-os/utils/kl/asm.c (revision 4d1cf5269ce9db7a55c9be8fb51fda675c5d8223)
174a4d8c2SCharles.Forsyth #include	"l.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth #define	LPUT(c)\
474a4d8c2SCharles.Forsyth 	{\
574a4d8c2SCharles.Forsyth 		cbp[0] = (c)>>24;\
674a4d8c2SCharles.Forsyth 		cbp[1] = (c)>>16;\
774a4d8c2SCharles.Forsyth 		cbp[2] = (c)>>8;\
874a4d8c2SCharles.Forsyth 		cbp[3] = (c);\
974a4d8c2SCharles.Forsyth 		cbp += 4;\
1074a4d8c2SCharles.Forsyth 		cbc -= 4;\
1174a4d8c2SCharles.Forsyth 		if(cbc <= 0)\
1274a4d8c2SCharles.Forsyth 			cflush();\
1374a4d8c2SCharles.Forsyth 	}
1474a4d8c2SCharles.Forsyth 
1574a4d8c2SCharles.Forsyth #define	CPUT(c)\
1674a4d8c2SCharles.Forsyth 	{\
1774a4d8c2SCharles.Forsyth 		cbp[0] = (c);\
1874a4d8c2SCharles.Forsyth 		cbp++;\
1974a4d8c2SCharles.Forsyth 		cbc--;\
2074a4d8c2SCharles.Forsyth 		if(cbc <= 0)\
2174a4d8c2SCharles.Forsyth 			cflush();\
2274a4d8c2SCharles.Forsyth 	}
2374a4d8c2SCharles.Forsyth 
2474a4d8c2SCharles.Forsyth long
entryvalue(void)2574a4d8c2SCharles.Forsyth entryvalue(void)
2674a4d8c2SCharles.Forsyth {
2774a4d8c2SCharles.Forsyth 	char *a;
2874a4d8c2SCharles.Forsyth 	Sym *s;
2974a4d8c2SCharles.Forsyth 
3074a4d8c2SCharles.Forsyth 	a = INITENTRY;
3174a4d8c2SCharles.Forsyth 	if(*a >= '0' && *a <= '9')
3274a4d8c2SCharles.Forsyth 		return atolwhex(a);
3374a4d8c2SCharles.Forsyth 	s = lookup(a, 0);
3474a4d8c2SCharles.Forsyth 	if(s->type == 0)
3574a4d8c2SCharles.Forsyth 		return INITTEXT;
3674a4d8c2SCharles.Forsyth 	if(s->type != STEXT && s->type != SLEAF)
3774a4d8c2SCharles.Forsyth 		diag("entry not text: %s", s->name);
3874a4d8c2SCharles.Forsyth 	return s->value;
3974a4d8c2SCharles.Forsyth }
4074a4d8c2SCharles.Forsyth 
4174a4d8c2SCharles.Forsyth void
asmb(void)4274a4d8c2SCharles.Forsyth asmb(void)
4374a4d8c2SCharles.Forsyth {
4474a4d8c2SCharles.Forsyth 	Prog *p;
4574a4d8c2SCharles.Forsyth 	long t;
4674a4d8c2SCharles.Forsyth 	Optab *o;
4774a4d8c2SCharles.Forsyth 
4874a4d8c2SCharles.Forsyth 	if(debug['v'])
4974a4d8c2SCharles.Forsyth 		Bprint(&bso, "%5.2f asm\n", cputime());
5074a4d8c2SCharles.Forsyth 	Bflush(&bso);
5174a4d8c2SCharles.Forsyth 	seek(cout, HEADR, 0);
5274a4d8c2SCharles.Forsyth 	pc = INITTEXT;
5374a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
5474a4d8c2SCharles.Forsyth 		if(p->as == ATEXT) {
5574a4d8c2SCharles.Forsyth 			curtext = p;
5674a4d8c2SCharles.Forsyth 			autosize = p->to.offset + 4;
5774a4d8c2SCharles.Forsyth 		}
5874a4d8c2SCharles.Forsyth 		if(p->pc != pc) {
5974a4d8c2SCharles.Forsyth 			diag("phase error %lux sb %lux",
6074a4d8c2SCharles.Forsyth 				p->pc, pc);
6174a4d8c2SCharles.Forsyth 			if(!debug['a'])
6274a4d8c2SCharles.Forsyth 				prasm(curp);
6374a4d8c2SCharles.Forsyth 			pc = p->pc;
6474a4d8c2SCharles.Forsyth 		}
6574a4d8c2SCharles.Forsyth 		curp = p;
6674a4d8c2SCharles.Forsyth 		o = oplook(p);	/* could probably avoid this call */
6774a4d8c2SCharles.Forsyth 		if(asmout(p, o, 0)) {
6874a4d8c2SCharles.Forsyth 			p = p->link;
6974a4d8c2SCharles.Forsyth 			pc += 4;
7074a4d8c2SCharles.Forsyth 		}
7174a4d8c2SCharles.Forsyth 		pc += o->size;
7274a4d8c2SCharles.Forsyth 	}
7374a4d8c2SCharles.Forsyth 	if(debug['a'])
7474a4d8c2SCharles.Forsyth 		Bprint(&bso, "\n");
7574a4d8c2SCharles.Forsyth 	Bflush(&bso);
7674a4d8c2SCharles.Forsyth 	cflush();
7774a4d8c2SCharles.Forsyth 
7874a4d8c2SCharles.Forsyth 	curtext = P;
7974a4d8c2SCharles.Forsyth 	switch(HEADTYPE) {
8074a4d8c2SCharles.Forsyth 	case 0:
8174a4d8c2SCharles.Forsyth 	case 3:
8274a4d8c2SCharles.Forsyth 		seek(cout, HEADR+textsize, 0);
8374a4d8c2SCharles.Forsyth 		break;
8474a4d8c2SCharles.Forsyth 	case 1:
8574a4d8c2SCharles.Forsyth 	case 2:
8674a4d8c2SCharles.Forsyth 		seek(cout, HEADR+textsize, 0);
8774a4d8c2SCharles.Forsyth 		break;
8874a4d8c2SCharles.Forsyth 	}
8974a4d8c2SCharles.Forsyth 	for(t = 0; t < datsize; t += sizeof(buf)-100) {
9074a4d8c2SCharles.Forsyth 		if(datsize-t > sizeof(buf)-100)
9174a4d8c2SCharles.Forsyth 			datblk(t, sizeof(buf)-100);
9274a4d8c2SCharles.Forsyth 		else
9374a4d8c2SCharles.Forsyth 			datblk(t, datsize-t);
9474a4d8c2SCharles.Forsyth 	}
9574a4d8c2SCharles.Forsyth 
9674a4d8c2SCharles.Forsyth 	symsize = 0;
9774a4d8c2SCharles.Forsyth 	lcsize = 0;
9874a4d8c2SCharles.Forsyth 	if(!debug['s']) {
9974a4d8c2SCharles.Forsyth 		if(debug['v'])
10074a4d8c2SCharles.Forsyth 			Bprint(&bso, "%5.2f sym\n", cputime());
10174a4d8c2SCharles.Forsyth 		Bflush(&bso);
10274a4d8c2SCharles.Forsyth 		switch(HEADTYPE) {
10374a4d8c2SCharles.Forsyth 		case 0:
10474a4d8c2SCharles.Forsyth 		case 3:
10574a4d8c2SCharles.Forsyth 			seek(cout, HEADR+textsize+datsize, 0);
10674a4d8c2SCharles.Forsyth 			break;
10774a4d8c2SCharles.Forsyth 		case 2:
10874a4d8c2SCharles.Forsyth 		case 1:
10974a4d8c2SCharles.Forsyth 			seek(cout, HEADR+textsize+datsize, 0);
11074a4d8c2SCharles.Forsyth 			break;
11174a4d8c2SCharles.Forsyth 		}
11274a4d8c2SCharles.Forsyth 		if(!debug['s'])
11374a4d8c2SCharles.Forsyth 			asmsym();
11474a4d8c2SCharles.Forsyth 		if(debug['v'])
11574a4d8c2SCharles.Forsyth 			Bprint(&bso, "%5.2f sp\n", cputime());
11674a4d8c2SCharles.Forsyth 		Bflush(&bso);
11774a4d8c2SCharles.Forsyth 		if(!debug['s'])
11874a4d8c2SCharles.Forsyth 			asmlc();
11974a4d8c2SCharles.Forsyth 		 /* round up file length for boot image */
12074a4d8c2SCharles.Forsyth 		if(HEADTYPE == 0 || HEADTYPE == 3)
12174a4d8c2SCharles.Forsyth 			if((symsize+lcsize) & 1)
12274a4d8c2SCharles.Forsyth 				CPUT(0);
12374a4d8c2SCharles.Forsyth 		cflush();
12474a4d8c2SCharles.Forsyth 	}
12574a4d8c2SCharles.Forsyth 
12674a4d8c2SCharles.Forsyth 	seek(cout, 0L, 0);
12774a4d8c2SCharles.Forsyth 	switch(HEADTYPE) {
12874a4d8c2SCharles.Forsyth 	case 0:
12974a4d8c2SCharles.Forsyth 		lput(0x1030107);		/* magic and sections */
13074a4d8c2SCharles.Forsyth 		lput(textsize);			/* sizes */
13174a4d8c2SCharles.Forsyth 		lput(datsize);
13274a4d8c2SCharles.Forsyth 		lput(bsssize);
13374a4d8c2SCharles.Forsyth 		lput(symsize);			/* nsyms */
13474a4d8c2SCharles.Forsyth 		lput(entryvalue());		/* va of entry */
13574a4d8c2SCharles.Forsyth 		lput(0L);
13674a4d8c2SCharles.Forsyth 		lput(lcsize);
13774a4d8c2SCharles.Forsyth 		break;
13874a4d8c2SCharles.Forsyth 	case 1:
13974a4d8c2SCharles.Forsyth 		break;
14074a4d8c2SCharles.Forsyth 	case 2:
14174a4d8c2SCharles.Forsyth 		lput(4*13*13+7);		/* magic */
14274a4d8c2SCharles.Forsyth 		lput(textsize);			/* sizes */
14374a4d8c2SCharles.Forsyth 		lput(datsize);
14474a4d8c2SCharles.Forsyth 		lput(bsssize);
14574a4d8c2SCharles.Forsyth 		lput(symsize);			/* nsyms */
14674a4d8c2SCharles.Forsyth 		lput(entryvalue());		/* va of entry */
14774a4d8c2SCharles.Forsyth 		lput(0L);
14874a4d8c2SCharles.Forsyth 		lput(lcsize);
14974a4d8c2SCharles.Forsyth 		break;
15074a4d8c2SCharles.Forsyth 	case 3:
15174a4d8c2SCharles.Forsyth 		lput(0x1030107);		/* magic and sections */
15274a4d8c2SCharles.Forsyth 		lput(0x90100000);
15374a4d8c2SCharles.Forsyth #define SPARC_NOOP 0x01000000
15474a4d8c2SCharles.Forsyth 		lput(SPARC_NOOP);
15574a4d8c2SCharles.Forsyth 		lput(SPARC_NOOP);
15674a4d8c2SCharles.Forsyth 		lput(SPARC_NOOP);
15774a4d8c2SCharles.Forsyth 		lput(SPARC_NOOP);
15874a4d8c2SCharles.Forsyth 		lput(SPARC_NOOP);
15974a4d8c2SCharles.Forsyth 		lput(SPARC_NOOP);
16074a4d8c2SCharles.Forsyth 		break;
16174a4d8c2SCharles.Forsyth 	}
16274a4d8c2SCharles.Forsyth 	cflush();
16374a4d8c2SCharles.Forsyth }
16474a4d8c2SCharles.Forsyth 
16574a4d8c2SCharles.Forsyth void
lput(long l)16674a4d8c2SCharles.Forsyth lput(long l)
16774a4d8c2SCharles.Forsyth {
16874a4d8c2SCharles.Forsyth 
16974a4d8c2SCharles.Forsyth 	LPUT(l);
17074a4d8c2SCharles.Forsyth }
17174a4d8c2SCharles.Forsyth 
17274a4d8c2SCharles.Forsyth void
cflush(void)17374a4d8c2SCharles.Forsyth cflush(void)
17474a4d8c2SCharles.Forsyth {
17574a4d8c2SCharles.Forsyth 	int n;
17674a4d8c2SCharles.Forsyth 
17774a4d8c2SCharles.Forsyth 	n = sizeof(buf.cbuf) - cbc;
17874a4d8c2SCharles.Forsyth 	if(n)
17974a4d8c2SCharles.Forsyth 		write(cout, buf.cbuf, n);
18074a4d8c2SCharles.Forsyth 	cbp = buf.cbuf;
18174a4d8c2SCharles.Forsyth 	cbc = sizeof(buf.cbuf);
18274a4d8c2SCharles.Forsyth }
18374a4d8c2SCharles.Forsyth 
18474a4d8c2SCharles.Forsyth void
asmsym(void)18574a4d8c2SCharles.Forsyth asmsym(void)
18674a4d8c2SCharles.Forsyth {
18774a4d8c2SCharles.Forsyth 	Prog *p;
18874a4d8c2SCharles.Forsyth 	Auto *a;
18974a4d8c2SCharles.Forsyth 	Sym *s;
19074a4d8c2SCharles.Forsyth 	int h;
19174a4d8c2SCharles.Forsyth 
19274a4d8c2SCharles.Forsyth 	s = lookup("etext", 0);
19374a4d8c2SCharles.Forsyth 	if(s->type == STEXT)
19474a4d8c2SCharles.Forsyth 		putsymb(s->name, 'T', s->value, s->version);
19574a4d8c2SCharles.Forsyth 
19674a4d8c2SCharles.Forsyth 	for(h=0; h<NHASH; h++)
19774a4d8c2SCharles.Forsyth 		for(s=hash[h]; s!=S; s=s->link)
19874a4d8c2SCharles.Forsyth 			switch(s->type) {
19974a4d8c2SCharles.Forsyth 			case SCONST:
20074a4d8c2SCharles.Forsyth 				putsymb(s->name, 'D', s->value, s->version);
20174a4d8c2SCharles.Forsyth 				continue;
20274a4d8c2SCharles.Forsyth 
20374a4d8c2SCharles.Forsyth 			case SDATA:
20474a4d8c2SCharles.Forsyth 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
20574a4d8c2SCharles.Forsyth 				continue;
20674a4d8c2SCharles.Forsyth 
20774a4d8c2SCharles.Forsyth 			case SBSS:
20874a4d8c2SCharles.Forsyth 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
20974a4d8c2SCharles.Forsyth 				continue;
21074a4d8c2SCharles.Forsyth 
21174a4d8c2SCharles.Forsyth 			case SFILE:
21274a4d8c2SCharles.Forsyth 				putsymb(s->name, 'f', s->value, s->version);
21374a4d8c2SCharles.Forsyth 				continue;
21474a4d8c2SCharles.Forsyth 			}
21574a4d8c2SCharles.Forsyth 
21674a4d8c2SCharles.Forsyth 	for(p=textp; p!=P; p=p->cond) {
21774a4d8c2SCharles.Forsyth 		s = p->from.sym;
21874a4d8c2SCharles.Forsyth 		if(s->type != STEXT && s->type != SLEAF)
21974a4d8c2SCharles.Forsyth 			continue;
22074a4d8c2SCharles.Forsyth 
22174a4d8c2SCharles.Forsyth 		/* filenames first */
22274a4d8c2SCharles.Forsyth 		for(a=p->to.autom; a; a=a->link)
22374a4d8c2SCharles.Forsyth 			if(a->type == D_FILE)
22474a4d8c2SCharles.Forsyth 				putsymb(a->asym->name, 'z', a->aoffset, 0);
22574a4d8c2SCharles.Forsyth 			else
22674a4d8c2SCharles.Forsyth 			if(a->type == D_FILE1)
22774a4d8c2SCharles.Forsyth 				putsymb(a->asym->name, 'Z', a->aoffset, 0);
22874a4d8c2SCharles.Forsyth 
22974a4d8c2SCharles.Forsyth 		if(s->type == STEXT)
23074a4d8c2SCharles.Forsyth 			putsymb(s->name, 'T', s->value, s->version);
23174a4d8c2SCharles.Forsyth 		else
23274a4d8c2SCharles.Forsyth 			putsymb(s->name, 'L', s->value, s->version);
23374a4d8c2SCharles.Forsyth 
23474a4d8c2SCharles.Forsyth 		/* frame, auto and param after */
23574a4d8c2SCharles.Forsyth 		putsymb(".frame", 'm', p->to.offset+4, 0);
23674a4d8c2SCharles.Forsyth 		for(a=p->to.autom; a; a=a->link)
23774a4d8c2SCharles.Forsyth 			if(a->type == D_AUTO)
23874a4d8c2SCharles.Forsyth 				putsymb(a->asym->name, 'a', -a->aoffset, 0);
23974a4d8c2SCharles.Forsyth 			else
24074a4d8c2SCharles.Forsyth 			if(a->type == D_PARAM)
24174a4d8c2SCharles.Forsyth 				putsymb(a->asym->name, 'p', a->aoffset, 0);
24274a4d8c2SCharles.Forsyth 	}
24374a4d8c2SCharles.Forsyth 	if(debug['v'] || debug['n'])
24474a4d8c2SCharles.Forsyth 		Bprint(&bso, "symsize = %lud\n", symsize);
24574a4d8c2SCharles.Forsyth 	Bflush(&bso);
24674a4d8c2SCharles.Forsyth }
24774a4d8c2SCharles.Forsyth 
24874a4d8c2SCharles.Forsyth void
putsymb(char * s,int t,long v,int ver)24974a4d8c2SCharles.Forsyth putsymb(char *s, int t, long v, int ver)
25074a4d8c2SCharles.Forsyth {
25174a4d8c2SCharles.Forsyth 	int i, f;
25274a4d8c2SCharles.Forsyth 
25374a4d8c2SCharles.Forsyth 	if(t == 'f')
25474a4d8c2SCharles.Forsyth 		s++;
25574a4d8c2SCharles.Forsyth 	LPUT(v);
25674a4d8c2SCharles.Forsyth 	if(ver)
25774a4d8c2SCharles.Forsyth 		t += 'a' - 'A';
25874a4d8c2SCharles.Forsyth 	CPUT(t+0x80);			/* 0x80 is variable length */
25974a4d8c2SCharles.Forsyth 
26074a4d8c2SCharles.Forsyth 	if(t == 'Z' || t == 'z') {
26174a4d8c2SCharles.Forsyth 		CPUT(s[0]);
26274a4d8c2SCharles.Forsyth 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
26374a4d8c2SCharles.Forsyth 			CPUT(s[i]);
26474a4d8c2SCharles.Forsyth 			CPUT(s[i+1]);
26574a4d8c2SCharles.Forsyth 		}
26674a4d8c2SCharles.Forsyth 		CPUT(0);
26774a4d8c2SCharles.Forsyth 		CPUT(0);
26874a4d8c2SCharles.Forsyth 		i++;
26974a4d8c2SCharles.Forsyth 	}
27074a4d8c2SCharles.Forsyth 	else {
27174a4d8c2SCharles.Forsyth 		for(i=0; s[i]; i++)
27274a4d8c2SCharles.Forsyth 			CPUT(s[i]);
27374a4d8c2SCharles.Forsyth 		CPUT(0);
27474a4d8c2SCharles.Forsyth 	}
27574a4d8c2SCharles.Forsyth 	symsize += 4 + 1 + i + 1;
27674a4d8c2SCharles.Forsyth 
27774a4d8c2SCharles.Forsyth 	if(debug['n']) {
27874a4d8c2SCharles.Forsyth 		if(t == 'z' || t == 'Z') {
27974a4d8c2SCharles.Forsyth 			Bprint(&bso, "%c %.8lux ", t, v);
28074a4d8c2SCharles.Forsyth 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
28174a4d8c2SCharles.Forsyth 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
28274a4d8c2SCharles.Forsyth 				Bprint(&bso, "/%x", f);
28374a4d8c2SCharles.Forsyth 			}
28474a4d8c2SCharles.Forsyth 			Bprint(&bso, "\n");
28574a4d8c2SCharles.Forsyth 			return;
28674a4d8c2SCharles.Forsyth 		}
28774a4d8c2SCharles.Forsyth 		if(ver)
28874a4d8c2SCharles.Forsyth 			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
28974a4d8c2SCharles.Forsyth 		else
29074a4d8c2SCharles.Forsyth 			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
29174a4d8c2SCharles.Forsyth 	}
29274a4d8c2SCharles.Forsyth }
29374a4d8c2SCharles.Forsyth 
29474a4d8c2SCharles.Forsyth #define	MINLC	4
29574a4d8c2SCharles.Forsyth void
asmlc(void)29674a4d8c2SCharles.Forsyth asmlc(void)
29774a4d8c2SCharles.Forsyth {
29874a4d8c2SCharles.Forsyth 	long oldpc, oldlc;
29974a4d8c2SCharles.Forsyth 	Prog *p;
30074a4d8c2SCharles.Forsyth 	long v, s;
30174a4d8c2SCharles.Forsyth 
30274a4d8c2SCharles.Forsyth 	oldpc = INITTEXT;
30374a4d8c2SCharles.Forsyth 	oldlc = 0;
30474a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
30574a4d8c2SCharles.Forsyth 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
30674a4d8c2SCharles.Forsyth 			if(p->as == ATEXT)
30774a4d8c2SCharles.Forsyth 				curtext = p;
30874a4d8c2SCharles.Forsyth 			if(debug['L'])
30974a4d8c2SCharles.Forsyth 				Bprint(&bso, "%6lux %P\n",
31074a4d8c2SCharles.Forsyth 					p->pc, p);
31174a4d8c2SCharles.Forsyth 			continue;
31274a4d8c2SCharles.Forsyth 		}
31374a4d8c2SCharles.Forsyth 		if(debug['L'])
31474a4d8c2SCharles.Forsyth 			Bprint(&bso, "\t\t%6ld", lcsize);
31574a4d8c2SCharles.Forsyth 		v = (p->pc - oldpc) / MINLC;
31674a4d8c2SCharles.Forsyth 		while(v) {
31774a4d8c2SCharles.Forsyth 			s = 127;
31874a4d8c2SCharles.Forsyth 			if(v < 127)
31974a4d8c2SCharles.Forsyth 				s = v;
32074a4d8c2SCharles.Forsyth 			CPUT(s+128);	/* 129-255 +pc */
32174a4d8c2SCharles.Forsyth 			if(debug['L'])
32274a4d8c2SCharles.Forsyth 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
32374a4d8c2SCharles.Forsyth 			v -= s;
32474a4d8c2SCharles.Forsyth 			lcsize++;
32574a4d8c2SCharles.Forsyth 		}
32674a4d8c2SCharles.Forsyth 		s = p->line - oldlc;
32774a4d8c2SCharles.Forsyth 		oldlc = p->line;
32874a4d8c2SCharles.Forsyth 		oldpc = p->pc + MINLC;
32974a4d8c2SCharles.Forsyth 		if(s > 64 || s < -64) {
33074a4d8c2SCharles.Forsyth 			CPUT(0);	/* 0 vv +lc */
33174a4d8c2SCharles.Forsyth 			CPUT(s>>24);
33274a4d8c2SCharles.Forsyth 			CPUT(s>>16);
33374a4d8c2SCharles.Forsyth 			CPUT(s>>8);
33474a4d8c2SCharles.Forsyth 			CPUT(s);
33574a4d8c2SCharles.Forsyth 			if(debug['L']) {
33674a4d8c2SCharles.Forsyth 				if(s > 0)
33774a4d8c2SCharles.Forsyth 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
33874a4d8c2SCharles.Forsyth 						s, 0, s);
33974a4d8c2SCharles.Forsyth 				else
34074a4d8c2SCharles.Forsyth 					Bprint(&bso, " lc%ld(%d,%ld)\n",
34174a4d8c2SCharles.Forsyth 						s, 0, s);
34274a4d8c2SCharles.Forsyth 				Bprint(&bso, "%6lux %P\n",
34374a4d8c2SCharles.Forsyth 					p->pc, p);
34474a4d8c2SCharles.Forsyth 			}
34574a4d8c2SCharles.Forsyth 			lcsize += 5;
34674a4d8c2SCharles.Forsyth 			continue;
34774a4d8c2SCharles.Forsyth 		}
34874a4d8c2SCharles.Forsyth 		if(s > 0) {
34974a4d8c2SCharles.Forsyth 			CPUT(0+s);	/* 1-64 +lc */
35074a4d8c2SCharles.Forsyth 			if(debug['L']) {
35174a4d8c2SCharles.Forsyth 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
35274a4d8c2SCharles.Forsyth 				Bprint(&bso, "%6lux %P\n",
35374a4d8c2SCharles.Forsyth 					p->pc, p);
35474a4d8c2SCharles.Forsyth 			}
35574a4d8c2SCharles.Forsyth 		} else {
35674a4d8c2SCharles.Forsyth 			CPUT(64-s);	/* 65-128 -lc */
35774a4d8c2SCharles.Forsyth 			if(debug['L']) {
35874a4d8c2SCharles.Forsyth 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
35974a4d8c2SCharles.Forsyth 				Bprint(&bso, "%6lux %P\n",
36074a4d8c2SCharles.Forsyth 					p->pc, p);
36174a4d8c2SCharles.Forsyth 			}
36274a4d8c2SCharles.Forsyth 		}
36374a4d8c2SCharles.Forsyth 		lcsize++;
36474a4d8c2SCharles.Forsyth 	}
36574a4d8c2SCharles.Forsyth 	while(lcsize & 1) {
36674a4d8c2SCharles.Forsyth 		s = 129;
36774a4d8c2SCharles.Forsyth 		CPUT(s);
36874a4d8c2SCharles.Forsyth 		lcsize++;
36974a4d8c2SCharles.Forsyth 	}
37074a4d8c2SCharles.Forsyth 	if(debug['v'] || debug['L'])
37174a4d8c2SCharles.Forsyth 		Bprint(&bso, "lcsize = %ld\n", lcsize);
37274a4d8c2SCharles.Forsyth 	Bflush(&bso);
37374a4d8c2SCharles.Forsyth }
37474a4d8c2SCharles.Forsyth 
37574a4d8c2SCharles.Forsyth void
datblk(long s,long n)37674a4d8c2SCharles.Forsyth datblk(long s, long n)
37774a4d8c2SCharles.Forsyth {
37874a4d8c2SCharles.Forsyth 	Prog *p;
37974a4d8c2SCharles.Forsyth 	char *cast;
38074a4d8c2SCharles.Forsyth 	long l, fl, j, d;
38174a4d8c2SCharles.Forsyth 	int i, c;
38274a4d8c2SCharles.Forsyth 
38374a4d8c2SCharles.Forsyth 	memset(buf.dbuf, 0, n+100);
38474a4d8c2SCharles.Forsyth 	for(p = datap; p != P; p = p->link) {
38574a4d8c2SCharles.Forsyth 		curp = p;
38674a4d8c2SCharles.Forsyth 		l = p->from.sym->value + p->from.offset - s;
38774a4d8c2SCharles.Forsyth 		c = p->reg;
38874a4d8c2SCharles.Forsyth 		i = 0;
38974a4d8c2SCharles.Forsyth 		if(l < 0) {
39074a4d8c2SCharles.Forsyth 			if(l+c <= 0)
39174a4d8c2SCharles.Forsyth 				continue;
39274a4d8c2SCharles.Forsyth 			while(l < 0) {
39374a4d8c2SCharles.Forsyth 				l++;
39474a4d8c2SCharles.Forsyth 				i++;
39574a4d8c2SCharles.Forsyth 			}
39674a4d8c2SCharles.Forsyth 		}
39774a4d8c2SCharles.Forsyth 		if(l >= n)
39874a4d8c2SCharles.Forsyth 			continue;
39974a4d8c2SCharles.Forsyth 		if(p->as != AINIT && p->as != ADYNT) {
40074a4d8c2SCharles.Forsyth 			for(j=l+(c-i)-1; j>=l; j--)
40174a4d8c2SCharles.Forsyth 				if(buf.dbuf[j]) {
40274a4d8c2SCharles.Forsyth 					print("%P\n", p);
40374a4d8c2SCharles.Forsyth 					diag("multiple initialization");
40474a4d8c2SCharles.Forsyth 					break;
40574a4d8c2SCharles.Forsyth 				}
40674a4d8c2SCharles.Forsyth 		}
40774a4d8c2SCharles.Forsyth 		switch(p->to.type) {
40874a4d8c2SCharles.Forsyth 		default:
40974a4d8c2SCharles.Forsyth 			diag("unknown mode in initialization\n%P", p);
41074a4d8c2SCharles.Forsyth 			break;
41174a4d8c2SCharles.Forsyth 
41274a4d8c2SCharles.Forsyth 		case D_FCONST:
41374a4d8c2SCharles.Forsyth 			switch(c) {
41474a4d8c2SCharles.Forsyth 			default:
41574a4d8c2SCharles.Forsyth 			case 4:
41674a4d8c2SCharles.Forsyth 				fl = ieeedtof(&p->to.ieee);
41774a4d8c2SCharles.Forsyth 				cast = (char*)&fl;
41874a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
41974a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[fnuxi8[i+4]];
42074a4d8c2SCharles.Forsyth 					l++;
42174a4d8c2SCharles.Forsyth 				}
42274a4d8c2SCharles.Forsyth 				break;
42374a4d8c2SCharles.Forsyth 			case 8:
42474a4d8c2SCharles.Forsyth 				cast = (char*)&p->to.ieee;
42574a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
42674a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[fnuxi8[i]];
42774a4d8c2SCharles.Forsyth 					l++;
42874a4d8c2SCharles.Forsyth 				}
42974a4d8c2SCharles.Forsyth 				break;
43074a4d8c2SCharles.Forsyth 			}
43174a4d8c2SCharles.Forsyth 			break;
43274a4d8c2SCharles.Forsyth 
43374a4d8c2SCharles.Forsyth 		case D_SCONST:
43474a4d8c2SCharles.Forsyth 			for(; i<c; i++) {
43574a4d8c2SCharles.Forsyth 				buf.dbuf[l] = p->to.sval[i];
43674a4d8c2SCharles.Forsyth 				l++;
43774a4d8c2SCharles.Forsyth 			}
43874a4d8c2SCharles.Forsyth 			break;
43974a4d8c2SCharles.Forsyth 
44074a4d8c2SCharles.Forsyth 		case D_CONST:
44174a4d8c2SCharles.Forsyth 			d = p->to.offset;
44274a4d8c2SCharles.Forsyth 			if(p->to.sym) {
44374a4d8c2SCharles.Forsyth 				if(p->to.sym->type == STEXT ||
44474a4d8c2SCharles.Forsyth 				   p->to.sym->type == SLEAF)
44574a4d8c2SCharles.Forsyth 					d += p->to.sym->value;
44674a4d8c2SCharles.Forsyth 				if(p->to.sym->type == SDATA)
44774a4d8c2SCharles.Forsyth 					d += p->to.sym->value + INITDAT;
44874a4d8c2SCharles.Forsyth 				if(p->to.sym->type == SBSS)
44974a4d8c2SCharles.Forsyth 					d += p->to.sym->value + INITDAT;
45074a4d8c2SCharles.Forsyth 			}
45174a4d8c2SCharles.Forsyth 			cast = (char*)&d;
45274a4d8c2SCharles.Forsyth 			switch(c) {
45374a4d8c2SCharles.Forsyth 			default:
45474a4d8c2SCharles.Forsyth 				diag("bad nuxi %d %d\n%P", c, i, curp);
45574a4d8c2SCharles.Forsyth 				break;
45674a4d8c2SCharles.Forsyth 			case 1:
45774a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
45874a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[inuxi1[i]];
45974a4d8c2SCharles.Forsyth 					l++;
46074a4d8c2SCharles.Forsyth 				}
46174a4d8c2SCharles.Forsyth 				break;
46274a4d8c2SCharles.Forsyth 			case 2:
46374a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
46474a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[inuxi2[i]];
46574a4d8c2SCharles.Forsyth 					l++;
46674a4d8c2SCharles.Forsyth 				}
46774a4d8c2SCharles.Forsyth 				break;
46874a4d8c2SCharles.Forsyth 			case 4:
46974a4d8c2SCharles.Forsyth 				for(; i<c; i++) {
47074a4d8c2SCharles.Forsyth 					buf.dbuf[l] = cast[inuxi4[i]];
47174a4d8c2SCharles.Forsyth 					l++;
47274a4d8c2SCharles.Forsyth 				}
47374a4d8c2SCharles.Forsyth 				break;
47474a4d8c2SCharles.Forsyth 			}
47574a4d8c2SCharles.Forsyth 			break;
47674a4d8c2SCharles.Forsyth 		}
47774a4d8c2SCharles.Forsyth 	}
47874a4d8c2SCharles.Forsyth 	write(cout, buf.dbuf, n);
47974a4d8c2SCharles.Forsyth }
48074a4d8c2SCharles.Forsyth 
48174a4d8c2SCharles.Forsyth #define	OP2(x)	(0x80000000|((x)<<19))
48274a4d8c2SCharles.Forsyth #define	OP3(x)	(0xc0000000|((x)<<19))
48374a4d8c2SCharles.Forsyth #define	OPB(x)	(0x00800000|((x)<<25))
48474a4d8c2SCharles.Forsyth #define	OPT(x)	(0x81d02000|((x)<<25))
48574a4d8c2SCharles.Forsyth #define	OPF1(x)	(0x81a00000|((x)<<5))
48674a4d8c2SCharles.Forsyth #define	OPF2(x)	(0x81a80000|((x)<<5))
48774a4d8c2SCharles.Forsyth #define	OPFB(x)	(0x01800000|((x)<<25))
48874a4d8c2SCharles.Forsyth 
48974a4d8c2SCharles.Forsyth #define	OP_RRR(op,r1,r2,r3)\
49074a4d8c2SCharles.Forsyth 	(0x00000000 | op |\
49174a4d8c2SCharles.Forsyth 	(((r1)&31L)<<0) |\
49274a4d8c2SCharles.Forsyth 	(((r2)&31L)<<14) |\
49374a4d8c2SCharles.Forsyth 	(((r3)&31L)<<25))
49474a4d8c2SCharles.Forsyth #define	OP_IRR(op,i,r2,r3)\
49574a4d8c2SCharles.Forsyth 	(0x00002000L | (op) |\
49674a4d8c2SCharles.Forsyth 	(((i)&0x1fffL)<<0) |\
49774a4d8c2SCharles.Forsyth 	(((r2)&31L)<<14) |\
49874a4d8c2SCharles.Forsyth 	(((r3)&31L)<<25))
49974a4d8c2SCharles.Forsyth #define	OP_BRA(op,pc)\
50074a4d8c2SCharles.Forsyth 	((op) |\
50174a4d8c2SCharles.Forsyth 	(((pc)&0x3fffff)<<0))
50274a4d8c2SCharles.Forsyth 
50374a4d8c2SCharles.Forsyth int
asmout(Prog * p,Optab * o,int aflag)50474a4d8c2SCharles.Forsyth asmout(Prog *p, Optab *o, int aflag)
50574a4d8c2SCharles.Forsyth {
50674a4d8c2SCharles.Forsyth 	long o1, o2, o3, o4, o5, v;
50774a4d8c2SCharles.Forsyth 	Prog *ct;
50874a4d8c2SCharles.Forsyth 	int r;
50974a4d8c2SCharles.Forsyth 
51074a4d8c2SCharles.Forsyth 	o1 = 0;
51174a4d8c2SCharles.Forsyth 	o2 = 0;
51274a4d8c2SCharles.Forsyth 	o3 = 0;
51374a4d8c2SCharles.Forsyth 	o4 = 0;
51474a4d8c2SCharles.Forsyth 	o5 = 0;
51574a4d8c2SCharles.Forsyth 
51674a4d8c2SCharles.Forsyth 	switch(o->type) {
51774a4d8c2SCharles.Forsyth 	default:
51874a4d8c2SCharles.Forsyth 		if(aflag)
51974a4d8c2SCharles.Forsyth 			return 0;
52074a4d8c2SCharles.Forsyth 		diag("unknown type %d", o->type);
52174a4d8c2SCharles.Forsyth 		if(!debug['a'])
52274a4d8c2SCharles.Forsyth 			prasm(p);
52374a4d8c2SCharles.Forsyth 		break;
52474a4d8c2SCharles.Forsyth 
52574a4d8c2SCharles.Forsyth 	case 0:		/* pseudo ops */
52674a4d8c2SCharles.Forsyth 		if(aflag) {
52774a4d8c2SCharles.Forsyth 			if(p->link) {
52874a4d8c2SCharles.Forsyth 				if(p->as == ATEXT) {
52974a4d8c2SCharles.Forsyth 					ct = curtext;
53074a4d8c2SCharles.Forsyth 					o2 = autosize;
53174a4d8c2SCharles.Forsyth 					curtext = p;
53274a4d8c2SCharles.Forsyth 					autosize = p->to.offset + 4;
53374a4d8c2SCharles.Forsyth 					o1 = asmout(p->link, oplook(p->link), aflag);
53474a4d8c2SCharles.Forsyth 					curtext = ct;
53574a4d8c2SCharles.Forsyth 					autosize = o2;
53674a4d8c2SCharles.Forsyth 				} else
53774a4d8c2SCharles.Forsyth 					o1 = asmout(p->link, oplook(p->link), aflag);
53874a4d8c2SCharles.Forsyth 			}
53974a4d8c2SCharles.Forsyth 			return o1;
54074a4d8c2SCharles.Forsyth 		}
54174a4d8c2SCharles.Forsyth 		break;
54274a4d8c2SCharles.Forsyth 
54374a4d8c2SCharles.Forsyth 	case 1:		/* mov r1,r2 ==> OR r1,r0,r2 */
54474a4d8c2SCharles.Forsyth 		o1 = OP_RRR(opcode(AOR), p->from.reg, REGZERO, p->to.reg);
54574a4d8c2SCharles.Forsyth 		break;
54674a4d8c2SCharles.Forsyth 
54774a4d8c2SCharles.Forsyth 	case 2:		/* mov $c,r ==> add r1,r0,r2 */
54874a4d8c2SCharles.Forsyth 		r = p->from.reg;
54974a4d8c2SCharles.Forsyth 		if(r == NREG)
55074a4d8c2SCharles.Forsyth 			r = o->param;
55174a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
55274a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(AADD), v, r, p->to.reg);
55374a4d8c2SCharles.Forsyth 		break;
55474a4d8c2SCharles.Forsyth 
55574a4d8c2SCharles.Forsyth 	case 3:		/* mov soreg, r */
55674a4d8c2SCharles.Forsyth 		r = p->from.reg;
55774a4d8c2SCharles.Forsyth 		if(r == NREG)
55874a4d8c2SCharles.Forsyth 			r = o->param;
55974a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
56074a4d8c2SCharles.Forsyth 		if(v == 0 && p->reg != NREG)
56174a4d8c2SCharles.Forsyth 			o1 = OP_RRR(opcode(p->as), p->reg, r, p->to.reg);
56274a4d8c2SCharles.Forsyth 		else
56374a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
56474a4d8c2SCharles.Forsyth 		break;
56574a4d8c2SCharles.Forsyth 
56674a4d8c2SCharles.Forsyth 	case 4:		/* mov r, soreg */
56774a4d8c2SCharles.Forsyth 		r = p->to.reg;
56874a4d8c2SCharles.Forsyth 		if(r == NREG)
56974a4d8c2SCharles.Forsyth 			r = o->param;
57074a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
57174a4d8c2SCharles.Forsyth 		if(v == 0 && p->reg != NREG)
57274a4d8c2SCharles.Forsyth 			o1 = OP_RRR(opcode(p->as+AEND), p->reg, r, p->from.reg);
57374a4d8c2SCharles.Forsyth 		else
57474a4d8c2SCharles.Forsyth 			o1 = OP_IRR(opcode(p->as+AEND), v, r, p->from.reg);
57574a4d8c2SCharles.Forsyth 		break;
57674a4d8c2SCharles.Forsyth 
57774a4d8c2SCharles.Forsyth 	case 5:		/* mov $lcon, reg => sethi, add */
57874a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
57974a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
58074a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
58174a4d8c2SCharles.Forsyth 		break;
58274a4d8c2SCharles.Forsyth 
58374a4d8c2SCharles.Forsyth 	case 6:		/* mov asi, r[+r] */
58474a4d8c2SCharles.Forsyth 		o1 = OP_RRR(opcode(p->as), p->reg, p->from.reg, p->to.reg);
58574a4d8c2SCharles.Forsyth 		o1 |= (1<<23) | ((p->from.offset&0xff)<<5);
58674a4d8c2SCharles.Forsyth 		break;
58774a4d8c2SCharles.Forsyth 
58874a4d8c2SCharles.Forsyth 	case 7:		/* mov [+r]r, asi */
58974a4d8c2SCharles.Forsyth 		o1 = OP_RRR(opcode(p->as+AEND), p->reg, p->to.reg, p->from.reg);
59074a4d8c2SCharles.Forsyth 		o1 |= (1<<23) | ((p->to.offset&0xff)<<5);
59174a4d8c2SCharles.Forsyth 		break;
59274a4d8c2SCharles.Forsyth 
59374a4d8c2SCharles.Forsyth 	case 8:		/* mov r, preg and mov preg, r */
59474a4d8c2SCharles.Forsyth 		if(p->to.type == D_PREG) {
59574a4d8c2SCharles.Forsyth 			r = p->from.reg;
59674a4d8c2SCharles.Forsyth 			switch(p->to.reg)
59774a4d8c2SCharles.Forsyth 			{
59874a4d8c2SCharles.Forsyth 			default:
59974a4d8c2SCharles.Forsyth 				diag("unknown register P%d", p->to.reg);
60074a4d8c2SCharles.Forsyth 			case D_Y:
60174a4d8c2SCharles.Forsyth 				o1 = OP2(48);	/* wry */
60274a4d8c2SCharles.Forsyth 				break;
60374a4d8c2SCharles.Forsyth 			case D_PSR:
60474a4d8c2SCharles.Forsyth 				o1 = OP2(49);	/* wrpsr */
60574a4d8c2SCharles.Forsyth 				break;
60674a4d8c2SCharles.Forsyth 			case D_WIM:
60774a4d8c2SCharles.Forsyth 				o1 = OP2(50);	/* wrwim */
60874a4d8c2SCharles.Forsyth 				break;
60974a4d8c2SCharles.Forsyth 			case D_TBR:
61074a4d8c2SCharles.Forsyth 				o1 = OP2(51);	/* wrtbr */
61174a4d8c2SCharles.Forsyth 				break;
61274a4d8c2SCharles.Forsyth 			}
61374a4d8c2SCharles.Forsyth 			o1 = OP_IRR(o1, 0, r, 0);
61474a4d8c2SCharles.Forsyth 			break;
61574a4d8c2SCharles.Forsyth 		}
61674a4d8c2SCharles.Forsyth 		if(p->from.type == D_PREG) {
61774a4d8c2SCharles.Forsyth 			r = p->to.reg;
61874a4d8c2SCharles.Forsyth 			switch(p->from.reg)
61974a4d8c2SCharles.Forsyth 			{
62074a4d8c2SCharles.Forsyth 			default:
62174a4d8c2SCharles.Forsyth 				diag("unknown register P%d", p->to.reg);
62274a4d8c2SCharles.Forsyth 			case D_Y:
62374a4d8c2SCharles.Forsyth 				o1 = OP2(40);	/* rdy */
62474a4d8c2SCharles.Forsyth 				break;
62574a4d8c2SCharles.Forsyth 			case D_PSR:
62674a4d8c2SCharles.Forsyth 				o1 = OP2(41);	/* rdpsr */
62774a4d8c2SCharles.Forsyth 				break;
62874a4d8c2SCharles.Forsyth 			case D_WIM:
62974a4d8c2SCharles.Forsyth 				o1 = OP2(42);	/* rdwim */
63074a4d8c2SCharles.Forsyth 				break;
63174a4d8c2SCharles.Forsyth 			case D_TBR:
63274a4d8c2SCharles.Forsyth 				o1 = OP2(43);	/* rdtbr */
63374a4d8c2SCharles.Forsyth 				break;
63474a4d8c2SCharles.Forsyth 			}
63574a4d8c2SCharles.Forsyth 			o1 = OP_RRR(o1, 0, 0, r);
63674a4d8c2SCharles.Forsyth 			break;
63774a4d8c2SCharles.Forsyth 		}
63874a4d8c2SCharles.Forsyth 		break;
63974a4d8c2SCharles.Forsyth 
64074a4d8c2SCharles.Forsyth 	case 9:		/* movb r,r */
64174a4d8c2SCharles.Forsyth 		v = 24;
64274a4d8c2SCharles.Forsyth 		if(p->as == AMOVH || p->as == AMOVHU)
64374a4d8c2SCharles.Forsyth 			v = 16;
64474a4d8c2SCharles.Forsyth 		r = ASRA;
64574a4d8c2SCharles.Forsyth 		if(p->as == AMOVBU || p->as == AMOVHU)
64674a4d8c2SCharles.Forsyth 			r = ASRL;
64774a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(ASLL), v, p->from.reg, p->to.reg);
64874a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opcode(r), v, p->to.reg, p->to.reg);
64974a4d8c2SCharles.Forsyth 		break;
65074a4d8c2SCharles.Forsyth 
65174a4d8c2SCharles.Forsyth 	case 10:	/* mov $loreg, reg */
65274a4d8c2SCharles.Forsyth 		r = p->from.reg;
65374a4d8c2SCharles.Forsyth 		if(r == NREG)
65474a4d8c2SCharles.Forsyth 			r = o->param;
65574a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
65674a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
65774a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
65874a4d8c2SCharles.Forsyth 		o3 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
65974a4d8c2SCharles.Forsyth 		break;
66074a4d8c2SCharles.Forsyth 
66174a4d8c2SCharles.Forsyth 	case 11:	/* mov loreg, r */
66274a4d8c2SCharles.Forsyth 		r = p->from.reg;
66374a4d8c2SCharles.Forsyth 		if(r == NREG)
66474a4d8c2SCharles.Forsyth 			r = o->param;
66574a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
66674a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
66774a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
66874a4d8c2SCharles.Forsyth 		o3 = OP_IRR(opcode(p->as), (v&0x3ff), REGTMP, p->to.reg);
66974a4d8c2SCharles.Forsyth 		break;
67074a4d8c2SCharles.Forsyth 
67174a4d8c2SCharles.Forsyth 	case 12:	/* mov r, loreg */
67274a4d8c2SCharles.Forsyth 		r = p->to.reg;
67374a4d8c2SCharles.Forsyth 		if(r == NREG)
67474a4d8c2SCharles.Forsyth 			r = o->param;
67574a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
67674a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
67774a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
67874a4d8c2SCharles.Forsyth 		o3 = OP_IRR(opcode(p->as+AEND), (v&0x3ff), REGTMP, p->from.reg);
67974a4d8c2SCharles.Forsyth 		break;
68074a4d8c2SCharles.Forsyth 
68174a4d8c2SCharles.Forsyth 	case 13:	/* mov $ucon, r */
68274a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
68374a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (p->to.reg<<25) | ((v>>10) & 0x3fffff);	/* sethi */
68474a4d8c2SCharles.Forsyth 		break;
68574a4d8c2SCharles.Forsyth 
68674a4d8c2SCharles.Forsyth 	case 20:	/* op $scon,r */
68774a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
68874a4d8c2SCharles.Forsyth 		r = p->reg;
68974a4d8c2SCharles.Forsyth 		if(r == NREG)
69074a4d8c2SCharles.Forsyth 			r = p->to.reg;
69174a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
69274a4d8c2SCharles.Forsyth 		break;
69374a4d8c2SCharles.Forsyth 
69474a4d8c2SCharles.Forsyth 	case 21:	/* op r1,r2 */
69574a4d8c2SCharles.Forsyth 		r = p->reg;
69674a4d8c2SCharles.Forsyth 		if(r == NREG)
69774a4d8c2SCharles.Forsyth 			r = p->to.reg;
69874a4d8c2SCharles.Forsyth 		o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
69974a4d8c2SCharles.Forsyth 		break;
70074a4d8c2SCharles.Forsyth 
70174a4d8c2SCharles.Forsyth 	case 22:	/* op $lcon,r */
70274a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
70374a4d8c2SCharles.Forsyth 		r = p->reg;
70474a4d8c2SCharles.Forsyth 		if(r == NREG)
70574a4d8c2SCharles.Forsyth 			r = p->to.reg;
70674a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
70774a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, REGTMP);
70874a4d8c2SCharles.Forsyth 		o3 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
70974a4d8c2SCharles.Forsyth 		break;
71074a4d8c2SCharles.Forsyth 
71174a4d8c2SCharles.Forsyth 	case 23:	/* cmp r,r */
71274a4d8c2SCharles.Forsyth 		o1 = OP_RRR(opcode(ASUBCC), p->to.reg, p->from.reg, REGZERO);
71374a4d8c2SCharles.Forsyth 		break;
71474a4d8c2SCharles.Forsyth 
71574a4d8c2SCharles.Forsyth 	case 24:	/* cmp r,$c */
71674a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
71774a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(ASUBCC), v, p->from.reg, REGZERO);
71874a4d8c2SCharles.Forsyth 		break;
71974a4d8c2SCharles.Forsyth 
72074a4d8c2SCharles.Forsyth 	case 25:	/* cmp $c,r BOTCH, fix compiler */
72174a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
72274a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(AADD), v, NREG, REGTMP);
72374a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(ASUBCC), p->to.reg, REGTMP, REGZERO);
72474a4d8c2SCharles.Forsyth 		break;
72574a4d8c2SCharles.Forsyth 
72674a4d8c2SCharles.Forsyth 	case 26:	/* op $ucon,r */
72774a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
72874a4d8c2SCharles.Forsyth 		r = p->reg;
72974a4d8c2SCharles.Forsyth 		if(r == NREG)
73074a4d8c2SCharles.Forsyth 			r = p->to.reg;
73174a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
73274a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
73374a4d8c2SCharles.Forsyth 		break;
73474a4d8c2SCharles.Forsyth 
73574a4d8c2SCharles.Forsyth 	case 30:	/* jmp/jmpl soreg */
73674a4d8c2SCharles.Forsyth 		if(aflag)
73774a4d8c2SCharles.Forsyth 			return 0;
73874a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
73974a4d8c2SCharles.Forsyth 		r = p->reg;
74074a4d8c2SCharles.Forsyth 		if(r == NREG && p->as == AJMPL)
74174a4d8c2SCharles.Forsyth 			r = 15;
74274a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(AJMPL), v, p->to.reg, r);
74374a4d8c2SCharles.Forsyth 		break;
74474a4d8c2SCharles.Forsyth 
74574a4d8c2SCharles.Forsyth 	case 31:	/* ba jmp */
74674a4d8c2SCharles.Forsyth 		if(aflag)
74774a4d8c2SCharles.Forsyth 			return 0;
74874a4d8c2SCharles.Forsyth 		r = p->as;
74974a4d8c2SCharles.Forsyth 		if(r == AJMP)
75074a4d8c2SCharles.Forsyth 			r = ABA;
75174a4d8c2SCharles.Forsyth 		v = 0;
75274a4d8c2SCharles.Forsyth 		if(p->cond)
75374a4d8c2SCharles.Forsyth 			v = p->cond->pc - p->pc;
75474a4d8c2SCharles.Forsyth 		o1 = OP_BRA(opcode(r), v/4);
75574a4d8c2SCharles.Forsyth 		if(r == ABA && p->link && p->cond && isnop(p->link)) {
75674a4d8c2SCharles.Forsyth 			o2 = asmout(p->cond, oplook(p->cond), 1);
75774a4d8c2SCharles.Forsyth 			if(o2) {
75874a4d8c2SCharles.Forsyth 				o1 += 1;
75974a4d8c2SCharles.Forsyth 				if(debug['a'])
76074a4d8c2SCharles.Forsyth 					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
76174a4d8c2SCharles.Forsyth 				LPUT(o1);
76274a4d8c2SCharles.Forsyth 				LPUT(o2);
76374a4d8c2SCharles.Forsyth 				return 1;
76474a4d8c2SCharles.Forsyth 			}
76574a4d8c2SCharles.Forsyth 			/* cant set annul here because pc has already been counted */
76674a4d8c2SCharles.Forsyth 		}
76774a4d8c2SCharles.Forsyth 		break;
76874a4d8c2SCharles.Forsyth 
76974a4d8c2SCharles.Forsyth 	case 32:	/* jmpl lbra */
77074a4d8c2SCharles.Forsyth 		if(aflag)
77174a4d8c2SCharles.Forsyth 			return 0;
77274a4d8c2SCharles.Forsyth 		v = 0;
77374a4d8c2SCharles.Forsyth 		if(p->cond)
77474a4d8c2SCharles.Forsyth 			v = p->cond->pc - p->pc;
77574a4d8c2SCharles.Forsyth 		r = p->reg;
77674a4d8c2SCharles.Forsyth 		if(r != NREG && r != 15)
77774a4d8c2SCharles.Forsyth 			diag("cant jmpl other than R15");
77874a4d8c2SCharles.Forsyth 		o1 = 0x40000000 | ((v/4) & 0x3fffffffL);	/* call */
77974a4d8c2SCharles.Forsyth 		if(p->link && p->cond && isnop(p->link)) {
78074a4d8c2SCharles.Forsyth 			o2 = asmout(p->cond, oplook(p->cond), 1);
78174a4d8c2SCharles.Forsyth 			if(o2) {
78274a4d8c2SCharles.Forsyth 				o1 += 1;
78374a4d8c2SCharles.Forsyth 				if(debug['a'])
78474a4d8c2SCharles.Forsyth 					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
78574a4d8c2SCharles.Forsyth 				LPUT(o1);
78674a4d8c2SCharles.Forsyth 				LPUT(o2);
78774a4d8c2SCharles.Forsyth 				return 1;
78874a4d8c2SCharles.Forsyth 			}
78974a4d8c2SCharles.Forsyth 		}
79074a4d8c2SCharles.Forsyth 		break;
79174a4d8c2SCharles.Forsyth 
79274a4d8c2SCharles.Forsyth 	case 33:	/* trap r */
79374a4d8c2SCharles.Forsyth 		if(aflag)
79474a4d8c2SCharles.Forsyth 			return 0;
79574a4d8c2SCharles.Forsyth 		o1 = opcode(p->as) | (p->from.reg<<14);
79674a4d8c2SCharles.Forsyth 		break;
79774a4d8c2SCharles.Forsyth 
79874a4d8c2SCharles.Forsyth 	case 34:	/* rett r1,r2 -> jmpl (r1); rett (r2) */
79974a4d8c2SCharles.Forsyth 		if(aflag)
80074a4d8c2SCharles.Forsyth 			return 0;
80174a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(AJMPL), 0, p->from.reg, REGZERO);
80274a4d8c2SCharles.Forsyth 		o2 = OP_IRR(opcode(ARETT), 0, p->to.reg, REGZERO);
80374a4d8c2SCharles.Forsyth 		break;
80474a4d8c2SCharles.Forsyth 
80574a4d8c2SCharles.Forsyth 	case 40:	/* ldfsr, stfsr, stdq */
80674a4d8c2SCharles.Forsyth 		if(p->to.type == D_PREG) {
80774a4d8c2SCharles.Forsyth 			r = p->from.reg;
80874a4d8c2SCharles.Forsyth 			if(r == NREG)
80974a4d8c2SCharles.Forsyth 				r = o->param;
81074a4d8c2SCharles.Forsyth 			v = regoff(&p->from);
81174a4d8c2SCharles.Forsyth 			if(p->to.reg == D_FSR) {
81274a4d8c2SCharles.Forsyth 				o1 = OP_IRR(OP3(33), v, r, 0);
81374a4d8c2SCharles.Forsyth 				break;
81474a4d8c2SCharles.Forsyth 			}
81574a4d8c2SCharles.Forsyth 			diag("unknown reg load %d", p->to.reg);
81674a4d8c2SCharles.Forsyth 		} else {
81774a4d8c2SCharles.Forsyth 			r = p->to.reg;
81874a4d8c2SCharles.Forsyth 			if(r == NREG)
81974a4d8c2SCharles.Forsyth 				r = o->param;
82074a4d8c2SCharles.Forsyth 			v = regoff(&p->to);
82174a4d8c2SCharles.Forsyth 			if(p->from.reg == D_FSR) {
82274a4d8c2SCharles.Forsyth 				o1 = OP_IRR(OP3(37), v, r, 0);
82374a4d8c2SCharles.Forsyth 				break;
82474a4d8c2SCharles.Forsyth 			}
82574a4d8c2SCharles.Forsyth 			if(p->as == AMOVD && p->from.reg == D_FPQ) {
82674a4d8c2SCharles.Forsyth 				o1 = OP_IRR(OP3(38), v, r, 0);
82774a4d8c2SCharles.Forsyth 				break;
82874a4d8c2SCharles.Forsyth 			}
82974a4d8c2SCharles.Forsyth 			diag("unknown reg store %d", p->from.reg);
83074a4d8c2SCharles.Forsyth 		}
83174a4d8c2SCharles.Forsyth 		break;
83274a4d8c2SCharles.Forsyth 
83374a4d8c2SCharles.Forsyth 	case 41:	/* ldf,ldd */
83474a4d8c2SCharles.Forsyth 		r = p->from.reg;
83574a4d8c2SCharles.Forsyth 		if(r == NREG)
83674a4d8c2SCharles.Forsyth 			r = o->param;
83774a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
83874a4d8c2SCharles.Forsyth 		if(p->as == AFMOVF || p->as == AMOVW) {
83974a4d8c2SCharles.Forsyth 			o1 = OP_IRR(OP3(32), v, r, p->to.reg);
84074a4d8c2SCharles.Forsyth 			break;
84174a4d8c2SCharles.Forsyth 		}
84274a4d8c2SCharles.Forsyth 		if(p->as == AMOVD || p->as == AFMOVD) {
84374a4d8c2SCharles.Forsyth 			o1 = OP_IRR(OP3(35), v, r, p->to.reg);
84474a4d8c2SCharles.Forsyth 			break;
84574a4d8c2SCharles.Forsyth 		}
84674a4d8c2SCharles.Forsyth 		diag("only MOVD and MOVW to FREG");
84774a4d8c2SCharles.Forsyth 		break;
84874a4d8c2SCharles.Forsyth 
84974a4d8c2SCharles.Forsyth 	case 42:	/* ldd -> ldf,ldf */
85074a4d8c2SCharles.Forsyth 		/* note should be ldd with proper allignment */
85174a4d8c2SCharles.Forsyth 		r = p->from.reg;
85274a4d8c2SCharles.Forsyth 		if(r == NREG)
85374a4d8c2SCharles.Forsyth 			r = o->param;
85474a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
85574a4d8c2SCharles.Forsyth 		o1 = OP_IRR(OP3(32), v, r, p->to.reg);
85674a4d8c2SCharles.Forsyth 		o2 = OP_IRR(OP3(32), v+4, r, p->to.reg+1);
85774a4d8c2SCharles.Forsyth 		break;
85874a4d8c2SCharles.Forsyth 
85974a4d8c2SCharles.Forsyth 	case 43:	/* stf */
86074a4d8c2SCharles.Forsyth 		r = p->to.reg;
86174a4d8c2SCharles.Forsyth 		if(r == NREG)
86274a4d8c2SCharles.Forsyth 			r = o->param;
86374a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
86474a4d8c2SCharles.Forsyth 		if(p->as == AFMOVF || p->as == AMOVW) {
86574a4d8c2SCharles.Forsyth 			o1 = OP_IRR(OP3(36), v, r, p->from.reg);
86674a4d8c2SCharles.Forsyth 			break;
86774a4d8c2SCharles.Forsyth 		}
86874a4d8c2SCharles.Forsyth 		if(p->as == AMOVD || p->as == AFMOVD) {
86974a4d8c2SCharles.Forsyth 			o1 = OP_IRR(OP3(39), v, r, p->from.reg);
87074a4d8c2SCharles.Forsyth 			break;
87174a4d8c2SCharles.Forsyth 		}
87274a4d8c2SCharles.Forsyth 		diag("only MOVD and MOVW from FREG");
87374a4d8c2SCharles.Forsyth 		break;
87474a4d8c2SCharles.Forsyth 
87574a4d8c2SCharles.Forsyth 	case 44:	/* std -> stf,stf */
87674a4d8c2SCharles.Forsyth 		/* note should be std with proper allignment */
87774a4d8c2SCharles.Forsyth 		r = p->to.reg;
87874a4d8c2SCharles.Forsyth 		if(r == NREG)
87974a4d8c2SCharles.Forsyth 			r = o->param;
88074a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
88174a4d8c2SCharles.Forsyth 		o1 = OP_IRR(OP3(36), v, r, p->from.reg);
88274a4d8c2SCharles.Forsyth 		o2 = OP_IRR(OP3(36), v+4, r, p->from.reg+1);
88374a4d8c2SCharles.Forsyth 		break;
88474a4d8c2SCharles.Forsyth 
88574a4d8c2SCharles.Forsyth 	case 45:	/* ldf lorg */
88674a4d8c2SCharles.Forsyth 		r = p->from.reg;
88774a4d8c2SCharles.Forsyth 		if(r == NREG)
88874a4d8c2SCharles.Forsyth 			r = o->param;
88974a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
89074a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
89174a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
89274a4d8c2SCharles.Forsyth 		o3 = OP_IRR(OP3(32), v&0x3ff, REGTMP, p->to.reg);
89374a4d8c2SCharles.Forsyth 		break;
89474a4d8c2SCharles.Forsyth 
89574a4d8c2SCharles.Forsyth 	case 46:	/* ldd lorg -> ldf,ldf */
89674a4d8c2SCharles.Forsyth 		/* note should be ldd with proper allignment */
89774a4d8c2SCharles.Forsyth 		r = p->from.reg;
89874a4d8c2SCharles.Forsyth 		if(r == NREG)
89974a4d8c2SCharles.Forsyth 			r = o->param;
90074a4d8c2SCharles.Forsyth 		v = regoff(&p->from);
90174a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
90274a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
90374a4d8c2SCharles.Forsyth 		o3 = OP_IRR(OP3(32), (v&0x3ff), REGTMP, p->to.reg);
90474a4d8c2SCharles.Forsyth 		o4 = OP_IRR(OP3(32), (v&0x3ff)+4, REGTMP, p->to.reg+1);
90574a4d8c2SCharles.Forsyth 		break;
90674a4d8c2SCharles.Forsyth 
90774a4d8c2SCharles.Forsyth 	case 47:	/* stf lorg */
90874a4d8c2SCharles.Forsyth 		r = p->to.reg;
90974a4d8c2SCharles.Forsyth 		if(r == NREG)
91074a4d8c2SCharles.Forsyth 			r = o->param;
91174a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
91274a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
91374a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
91474a4d8c2SCharles.Forsyth 		o3 = OP_IRR(OP3(36), v&0x3ff, REGTMP, p->from.reg);
91574a4d8c2SCharles.Forsyth 		break;
91674a4d8c2SCharles.Forsyth 
91774a4d8c2SCharles.Forsyth 	case 48:	/* std lorg -> stf,stf */
91874a4d8c2SCharles.Forsyth 		/* note should be std with proper allignment */
91974a4d8c2SCharles.Forsyth 		r = p->to.reg;
92074a4d8c2SCharles.Forsyth 		if(r == NREG)
92174a4d8c2SCharles.Forsyth 			r = o->param;
92274a4d8c2SCharles.Forsyth 		v = regoff(&p->to);
92374a4d8c2SCharles.Forsyth 		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
92474a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
92574a4d8c2SCharles.Forsyth 		o3 = OP_IRR(OP3(36), (v&0x3ff), REGTMP, p->from.reg);
92674a4d8c2SCharles.Forsyth 		o4 = OP_IRR(OP3(36), (v&0x3ff)+4, REGTMP, p->from.reg+1);
92774a4d8c2SCharles.Forsyth 		break;
92874a4d8c2SCharles.Forsyth 
92974a4d8c2SCharles.Forsyth 	case 49:	/* fmovd -> fmovf,fmovf */
93074a4d8c2SCharles.Forsyth 		o1 = OP_RRR(opcode(AFMOVF), p->from.reg, 0, p->to.reg);
93174a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(AFMOVF), p->from.reg+1, 0, p->to.reg+1);
93274a4d8c2SCharles.Forsyth 		break;
93374a4d8c2SCharles.Forsyth 
93474a4d8c2SCharles.Forsyth 	case 50:	/* fcmp */
93574a4d8c2SCharles.Forsyth 		o1 = OP_RRR(opcode(p->as), p->to.reg, p->from.reg, 0);
93674a4d8c2SCharles.Forsyth 		break;
93774a4d8c2SCharles.Forsyth 
93874a4d8c2SCharles.Forsyth 	case 51:	/* word */
93974a4d8c2SCharles.Forsyth 		if(aflag)
94074a4d8c2SCharles.Forsyth 			return 0;
94174a4d8c2SCharles.Forsyth 		o1 = regoff(&p->from);
94274a4d8c2SCharles.Forsyth 		break;
94374a4d8c2SCharles.Forsyth 
94474a4d8c2SCharles.Forsyth 	case 52:	/* div */
94574a4d8c2SCharles.Forsyth 		r = p->reg;
94674a4d8c2SCharles.Forsyth 		if(r == NREG)
94774a4d8c2SCharles.Forsyth 			r = p->to.reg;
94874a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
94974a4d8c2SCharles.Forsyth 		o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
95074a4d8c2SCharles.Forsyth 		o3 = OP_RRR(opcode(ADIV), p->from.reg, r, p->to.reg);
95174a4d8c2SCharles.Forsyth 		break;
95274a4d8c2SCharles.Forsyth 
95374a4d8c2SCharles.Forsyth 	case 53:	/* divl */
95474a4d8c2SCharles.Forsyth 		r = p->reg;
95574a4d8c2SCharles.Forsyth 		if(r == NREG)
95674a4d8c2SCharles.Forsyth 			r = p->to.reg;
95774a4d8c2SCharles.Forsyth 		o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
95874a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, p->to.reg);
95974a4d8c2SCharles.Forsyth 		break;
96074a4d8c2SCharles.Forsyth 
96174a4d8c2SCharles.Forsyth 	case 54:	/* mod */
96274a4d8c2SCharles.Forsyth 		r = p->reg;
96374a4d8c2SCharles.Forsyth 		if(r == NREG)
96474a4d8c2SCharles.Forsyth 			r = p->to.reg;
96574a4d8c2SCharles.Forsyth 		o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
96674a4d8c2SCharles.Forsyth 		o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
96774a4d8c2SCharles.Forsyth 		o3 = OP_RRR(opcode(ADIV), p->from.reg, r, REGTMP);
96874a4d8c2SCharles.Forsyth 		o4 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
96974a4d8c2SCharles.Forsyth 		o5 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
97074a4d8c2SCharles.Forsyth 		break;
97174a4d8c2SCharles.Forsyth 
97274a4d8c2SCharles.Forsyth 	case 55:	/* modl */
97374a4d8c2SCharles.Forsyth 		r = p->reg;
97474a4d8c2SCharles.Forsyth 		if(r == NREG)
97574a4d8c2SCharles.Forsyth 			r = p->to.reg;
97674a4d8c2SCharles.Forsyth 		o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
97774a4d8c2SCharles.Forsyth 		o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, REGTMP);
97874a4d8c2SCharles.Forsyth 		o3 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
97974a4d8c2SCharles.Forsyth 		o4 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
98074a4d8c2SCharles.Forsyth 		break;
98174a4d8c2SCharles.Forsyth 
98274a4d8c2SCharles.Forsyth 	case 56:	/* b(cc) -- annullable */
98374a4d8c2SCharles.Forsyth 		if(aflag)
98474a4d8c2SCharles.Forsyth 			return 0;
98574a4d8c2SCharles.Forsyth 		r = p->as;
98674a4d8c2SCharles.Forsyth 		v = 0;
98774a4d8c2SCharles.Forsyth 		if(p->cond)
98874a4d8c2SCharles.Forsyth 			v = p->cond->pc - p->pc;
98974a4d8c2SCharles.Forsyth 		o1 = OP_BRA(opcode(r), v/4);
99074a4d8c2SCharles.Forsyth 		if(p->link && p->cond && isnop(p->link))
99174a4d8c2SCharles.Forsyth 		if(!debug['A']) {
99274a4d8c2SCharles.Forsyth 			o2 = asmout(p->cond, oplook(p->cond), 2);
99374a4d8c2SCharles.Forsyth 			if(o2) {
99474a4d8c2SCharles.Forsyth 				o1 |= 1<<29;	/* annul */
99574a4d8c2SCharles.Forsyth 				o1 += 1;
99674a4d8c2SCharles.Forsyth 				if(debug['a'])
99774a4d8c2SCharles.Forsyth 					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
99874a4d8c2SCharles.Forsyth 				LPUT(o1);
99974a4d8c2SCharles.Forsyth 				LPUT(o2);
100074a4d8c2SCharles.Forsyth 				return 1;
100174a4d8c2SCharles.Forsyth 			}
100274a4d8c2SCharles.Forsyth 		}
100374a4d8c2SCharles.Forsyth 		break;
1004*4d1cf526Sforsyth 
1005*4d1cf526Sforsyth 	case 57:	/* op r1,r2 with reserved rs1 */
1006*4d1cf526Sforsyth 		r = 0;
1007*4d1cf526Sforsyth 		o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
1008*4d1cf526Sforsyth 		break;
100974a4d8c2SCharles.Forsyth 	}
101074a4d8c2SCharles.Forsyth 	if(aflag)
101174a4d8c2SCharles.Forsyth 		return o1;
101274a4d8c2SCharles.Forsyth 	v = p->pc;
101374a4d8c2SCharles.Forsyth 	switch(o->size) {
101474a4d8c2SCharles.Forsyth 	default:
101574a4d8c2SCharles.Forsyth 		if(debug['a'])
101674a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
101774a4d8c2SCharles.Forsyth 		break;
101874a4d8c2SCharles.Forsyth 	case 4:
101974a4d8c2SCharles.Forsyth 		if(debug['a'])
102074a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
102174a4d8c2SCharles.Forsyth 		LPUT(o1);
102274a4d8c2SCharles.Forsyth 		break;
102374a4d8c2SCharles.Forsyth 	case 8:
102474a4d8c2SCharles.Forsyth 		if(debug['a'])
102574a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
102674a4d8c2SCharles.Forsyth 		LPUT(o1);
102774a4d8c2SCharles.Forsyth 		LPUT(o2);
102874a4d8c2SCharles.Forsyth 		break;
102974a4d8c2SCharles.Forsyth 	case 12:
103074a4d8c2SCharles.Forsyth 		if(debug['a'])
103174a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
103274a4d8c2SCharles.Forsyth 		LPUT(o1);
103374a4d8c2SCharles.Forsyth 		LPUT(o2);
103474a4d8c2SCharles.Forsyth 		LPUT(o3);
103574a4d8c2SCharles.Forsyth 		break;
103674a4d8c2SCharles.Forsyth 	case 16:
103774a4d8c2SCharles.Forsyth 		if(debug['a'])
103874a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
103974a4d8c2SCharles.Forsyth 				v, o1, o2, o3, o4, p);
104074a4d8c2SCharles.Forsyth 		LPUT(o1);
104174a4d8c2SCharles.Forsyth 		LPUT(o2);
104274a4d8c2SCharles.Forsyth 		LPUT(o3);
104374a4d8c2SCharles.Forsyth 		LPUT(o4);
104474a4d8c2SCharles.Forsyth 		break;
104574a4d8c2SCharles.Forsyth 	case 20:
104674a4d8c2SCharles.Forsyth 		if(debug['a'])
104774a4d8c2SCharles.Forsyth 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
104874a4d8c2SCharles.Forsyth 				v, o1, o2, o3, o4, o5, p);
104974a4d8c2SCharles.Forsyth 		LPUT(o1);
105074a4d8c2SCharles.Forsyth 		LPUT(o2);
105174a4d8c2SCharles.Forsyth 		LPUT(o3);
105274a4d8c2SCharles.Forsyth 		LPUT(o4);
105374a4d8c2SCharles.Forsyth 		LPUT(o5);
105474a4d8c2SCharles.Forsyth 		break;
105574a4d8c2SCharles.Forsyth 	}
105674a4d8c2SCharles.Forsyth 	return 0;
105774a4d8c2SCharles.Forsyth }
105874a4d8c2SCharles.Forsyth 
105974a4d8c2SCharles.Forsyth int
isnop(Prog * p)106074a4d8c2SCharles.Forsyth isnop(Prog *p)
106174a4d8c2SCharles.Forsyth {
106274a4d8c2SCharles.Forsyth 	if(p->as != AORN)
106374a4d8c2SCharles.Forsyth 		return 0;
106474a4d8c2SCharles.Forsyth 	if(p->reg != REGZERO && p->reg != NREG)
106574a4d8c2SCharles.Forsyth 		return 0;
106674a4d8c2SCharles.Forsyth 	if(p->from.type != D_REG || p->from.reg != REGZERO)
106774a4d8c2SCharles.Forsyth 		return 0;
106874a4d8c2SCharles.Forsyth 	if(p->to.type != D_REG || p->to.reg != REGZERO)
106974a4d8c2SCharles.Forsyth 		return 0;
107074a4d8c2SCharles.Forsyth 	return 1;
107174a4d8c2SCharles.Forsyth }
107274a4d8c2SCharles.Forsyth 
107374a4d8c2SCharles.Forsyth long
opcode(int a)107474a4d8c2SCharles.Forsyth opcode(int a)
107574a4d8c2SCharles.Forsyth {
107674a4d8c2SCharles.Forsyth 	switch(a) {
107774a4d8c2SCharles.Forsyth 	case AADD:	return OP2(0);
107874a4d8c2SCharles.Forsyth 	case AADDCC:	return OP2(16);
107974a4d8c2SCharles.Forsyth 	case AADDX:	return OP2(8);
108074a4d8c2SCharles.Forsyth 	case AADDXCC:	return OP2(24);
108174a4d8c2SCharles.Forsyth 
108274a4d8c2SCharles.Forsyth 	case AMUL:	return OP2(10);
108374a4d8c2SCharles.Forsyth 	case ADIV:	return OP2(15);
108474a4d8c2SCharles.Forsyth 	case ADIVL:	return OP2(14);
108574a4d8c2SCharles.Forsyth 
108674a4d8c2SCharles.Forsyth 	case ATADDCC:	return OP2(32);
108774a4d8c2SCharles.Forsyth 	case ATADDCCTV:	return OP2(34);
108874a4d8c2SCharles.Forsyth 
108974a4d8c2SCharles.Forsyth 	case ASUB:	return OP2(4);
109074a4d8c2SCharles.Forsyth 	case ASUBCC:	return OP2(20);
109174a4d8c2SCharles.Forsyth 	case ASUBX:	return OP2(12);
109274a4d8c2SCharles.Forsyth 	case ASUBXCC:	return OP2(28);
109374a4d8c2SCharles.Forsyth 
109474a4d8c2SCharles.Forsyth 	case ATSUBCC:	return OP2(33);
109574a4d8c2SCharles.Forsyth 	case ATSUBCCTV:	return OP2(35);
109674a4d8c2SCharles.Forsyth 
109774a4d8c2SCharles.Forsyth 	case AMULSCC:	return OP2(36);
109874a4d8c2SCharles.Forsyth 	case ASAVE:	return OP2(60);
109974a4d8c2SCharles.Forsyth 	case ARESTORE:	return OP2(61);
110074a4d8c2SCharles.Forsyth 
110174a4d8c2SCharles.Forsyth 	case AAND:	return OP2(1);
110274a4d8c2SCharles.Forsyth 	case AANDCC:	return OP2(17);
110374a4d8c2SCharles.Forsyth 	case AANDN:	return OP2(5);
110474a4d8c2SCharles.Forsyth 	case AANDNCC:	return OP2(21);
110574a4d8c2SCharles.Forsyth 
110674a4d8c2SCharles.Forsyth 	case AOR:	return OP2(2);
110774a4d8c2SCharles.Forsyth 	case AORCC:	return OP2(18);
110874a4d8c2SCharles.Forsyth 	case AORN:	return OP2(6);
110974a4d8c2SCharles.Forsyth 	case AORNCC:	return OP2(22);
111074a4d8c2SCharles.Forsyth 
111174a4d8c2SCharles.Forsyth 	case AXOR:	return OP2(3);
111274a4d8c2SCharles.Forsyth 	case AXORCC:	return OP2(19);
111374a4d8c2SCharles.Forsyth 	case AXNOR:	return OP2(7);
111474a4d8c2SCharles.Forsyth 	case AXNORCC:	return OP2(23);
111574a4d8c2SCharles.Forsyth 
111674a4d8c2SCharles.Forsyth 	case ASLL:	return OP2(37);
111774a4d8c2SCharles.Forsyth 	case ASRL:	return OP2(38);
111874a4d8c2SCharles.Forsyth 	case ASRA:	return OP2(39);
111974a4d8c2SCharles.Forsyth 
112074a4d8c2SCharles.Forsyth 	case AJMPL:
112174a4d8c2SCharles.Forsyth 	case AJMP:	return OP2(56);
112274a4d8c2SCharles.Forsyth 	case ARETT:	return OP2(57);
112374a4d8c2SCharles.Forsyth 
112474a4d8c2SCharles.Forsyth 	case AMOVBU:	return OP3(1);	/* ldub */
112574a4d8c2SCharles.Forsyth 	case AMOVB:	return OP3(9);	/* ldsb */
112674a4d8c2SCharles.Forsyth 	case AMOVHU:	return OP3(2);	/* lduh */
112774a4d8c2SCharles.Forsyth 	case AMOVH:	return OP3(10);	/* ldsh */
112874a4d8c2SCharles.Forsyth 	case AMOVW:	return OP3(0);	/* ld */
112974a4d8c2SCharles.Forsyth 	case AMOVD:	return OP3(3);	/* ldd */
113074a4d8c2SCharles.Forsyth 
113174a4d8c2SCharles.Forsyth 	case AMOVBU+AEND:
113274a4d8c2SCharles.Forsyth 	case AMOVB+AEND:return OP3(5);	/* stb */
113374a4d8c2SCharles.Forsyth 
113474a4d8c2SCharles.Forsyth 	case AMOVHU+AEND:
113574a4d8c2SCharles.Forsyth 	case AMOVH+AEND:return OP3(6);	/* sth */
113674a4d8c2SCharles.Forsyth 
113774a4d8c2SCharles.Forsyth 	case AMOVW+AEND:return OP3(4);	/* st */
113874a4d8c2SCharles.Forsyth 
113974a4d8c2SCharles.Forsyth 	case AMOVD+AEND:return OP3(7);	/* std */
114074a4d8c2SCharles.Forsyth 
114174a4d8c2SCharles.Forsyth 	case ASWAP:			/* swap is symmetric */
114274a4d8c2SCharles.Forsyth 	case ASWAP+AEND:return OP3(15);
114374a4d8c2SCharles.Forsyth 
114474a4d8c2SCharles.Forsyth 	case ATAS:	return OP3(13);	/* tas is really ldstub */
114574a4d8c2SCharles.Forsyth 
114674a4d8c2SCharles.Forsyth 	case ABN:	return OPB(0);
114774a4d8c2SCharles.Forsyth 	case ABE:	return OPB(1);
114874a4d8c2SCharles.Forsyth 	case ABLE:	return OPB(2);
114974a4d8c2SCharles.Forsyth 	case ABL:	return OPB(3);
115074a4d8c2SCharles.Forsyth 	case ABLEU:	return OPB(4);
115174a4d8c2SCharles.Forsyth 	case ABCS:	return OPB(5);
115274a4d8c2SCharles.Forsyth 	case ABNEG:	return OPB(6);
115374a4d8c2SCharles.Forsyth 	case ABVS:	return OPB(7);
115474a4d8c2SCharles.Forsyth 	case ABA:	return OPB(8);
115574a4d8c2SCharles.Forsyth 	case ABNE:	return OPB(9);
115674a4d8c2SCharles.Forsyth 	case ABG:	return OPB(10);
115774a4d8c2SCharles.Forsyth 	case ABGE:	return OPB(11);
115874a4d8c2SCharles.Forsyth 	case ABGU:	return OPB(12);
115974a4d8c2SCharles.Forsyth 	case ABCC:	return OPB(13);
116074a4d8c2SCharles.Forsyth 	case ABPOS:	return OPB(14);
116174a4d8c2SCharles.Forsyth 	case ABVC:	return OPB(15);
116274a4d8c2SCharles.Forsyth 
116374a4d8c2SCharles.Forsyth 	case AFBA:	return OPFB(8);
116474a4d8c2SCharles.Forsyth 	case AFBE:	return OPFB(9);
116574a4d8c2SCharles.Forsyth 	case AFBG:	return OPFB(6);
116674a4d8c2SCharles.Forsyth 	case AFBGE:	return OPFB(11);
116774a4d8c2SCharles.Forsyth 	case AFBL:	return OPFB(4);
116874a4d8c2SCharles.Forsyth 	case AFBLE:	return OPFB(13);
116974a4d8c2SCharles.Forsyth 	case AFBLG:	return OPFB(2);
117074a4d8c2SCharles.Forsyth 	case AFBN:	return OPFB(0);
117174a4d8c2SCharles.Forsyth 	case AFBNE:	return OPFB(1);
117274a4d8c2SCharles.Forsyth 	case AFBO:	return OPFB(15);
117374a4d8c2SCharles.Forsyth 	case AFBU:	return OPFB(7);
117474a4d8c2SCharles.Forsyth 	case AFBUE:	return OPFB(10);
117574a4d8c2SCharles.Forsyth 	case AFBUG:	return OPFB(5);
117674a4d8c2SCharles.Forsyth 	case AFBUGE:	return OPFB(12);
117774a4d8c2SCharles.Forsyth 	case AFBUL:	return OPFB(3);
117874a4d8c2SCharles.Forsyth 	case AFBULE:	return OPFB(14);
117974a4d8c2SCharles.Forsyth 
118074a4d8c2SCharles.Forsyth 	case ATN:	return OPT(0);
118174a4d8c2SCharles.Forsyth 	case ATE:	return OPT(1);
118274a4d8c2SCharles.Forsyth 	case ATLE:	return OPT(2);
118374a4d8c2SCharles.Forsyth 	case ATL:	return OPT(3);
118474a4d8c2SCharles.Forsyth 	case ATLEU:	return OPT(4);
118574a4d8c2SCharles.Forsyth 	case ATCS:	return OPT(5);
118674a4d8c2SCharles.Forsyth 	case ATNEG:	return OPT(6);
118774a4d8c2SCharles.Forsyth 	case ATVS:	return OPT(7);
118874a4d8c2SCharles.Forsyth 	case ATA:	return OPT(8);
118974a4d8c2SCharles.Forsyth 	case ATNE:	return OPT(9);
119074a4d8c2SCharles.Forsyth 	case ATG:	return OPT(10);
119174a4d8c2SCharles.Forsyth 	case ATGE:	return OPT(11);
119274a4d8c2SCharles.Forsyth 	case ATGU:	return OPT(12);
119374a4d8c2SCharles.Forsyth 	case ATCC:	return OPT(13);
119474a4d8c2SCharles.Forsyth 	case ATPOS:	return OPT(14);
119574a4d8c2SCharles.Forsyth 	case ATVC:	return OPT(15);
119674a4d8c2SCharles.Forsyth 
119774a4d8c2SCharles.Forsyth 	case AFADDF:	return OPF1(65);
119874a4d8c2SCharles.Forsyth 	case AFADDD:	return OPF1(66);
119974a4d8c2SCharles.Forsyth 	case AFADDX:	return OPF1(67);
120074a4d8c2SCharles.Forsyth 	case AFSUBF:	return OPF1(69);
120174a4d8c2SCharles.Forsyth 	case AFSUBD:	return OPF1(70);
120274a4d8c2SCharles.Forsyth 	case AFSUBX:	return OPF1(71);
120374a4d8c2SCharles.Forsyth 	case AFMULF:	return OPF1(73);
120474a4d8c2SCharles.Forsyth 	case AFMULD:	return OPF1(74);
120574a4d8c2SCharles.Forsyth 	case AFMULX:	return OPF1(75);
120674a4d8c2SCharles.Forsyth 	case AFDIVF:	return OPF1(77);
120774a4d8c2SCharles.Forsyth 	case AFDIVD:	return OPF1(78);
120874a4d8c2SCharles.Forsyth 	case AFDIVX:	return OPF1(79);
120974a4d8c2SCharles.Forsyth 
121074a4d8c2SCharles.Forsyth 	case AFMOVF:	return OPF1(1);
121174a4d8c2SCharles.Forsyth 	case AFNEGF:	return OPF1(5);
121274a4d8c2SCharles.Forsyth 	case AFABSF:	return OPF1(9);
121374a4d8c2SCharles.Forsyth 
121474a4d8c2SCharles.Forsyth 	case AFSQRTF:	return OPF1(41);
121574a4d8c2SCharles.Forsyth 	case AFSQRTD:	return OPF1(42);
121674a4d8c2SCharles.Forsyth 	case AFSQRTX:	return OPF1(43);
121774a4d8c2SCharles.Forsyth 
121874a4d8c2SCharles.Forsyth 	case AFMOVWF:	return OPF1(196);
121974a4d8c2SCharles.Forsyth 	case AFMOVWD:	return OPF1(200);
122074a4d8c2SCharles.Forsyth 	case AFMOVWX:	return OPF1(204);
122174a4d8c2SCharles.Forsyth 	case AFMOVFW:	return OPF1(209);
122274a4d8c2SCharles.Forsyth 	case AFMOVDW:	return OPF1(210);
122374a4d8c2SCharles.Forsyth 	case AFMOVXW:	return OPF1(211);
122474a4d8c2SCharles.Forsyth 	case AFMOVFD:	return OPF1(201);
122574a4d8c2SCharles.Forsyth 	case AFMOVFX:	return OPF1(205);
122674a4d8c2SCharles.Forsyth 	case AFMOVDF:	return OPF1(198);
122774a4d8c2SCharles.Forsyth 	case AFMOVDX:	return OPF1(206);
122874a4d8c2SCharles.Forsyth 	case AFMOVXF:	return OPF1(199);
122974a4d8c2SCharles.Forsyth 	case AFMOVXD:	return OPF1(203);
123074a4d8c2SCharles.Forsyth 
123174a4d8c2SCharles.Forsyth 	case AFCMPF:	return OPF2(81);
123274a4d8c2SCharles.Forsyth 	case AFCMPD:	return OPF2(82);
123374a4d8c2SCharles.Forsyth 	case AFCMPX:	return OPF2(83);
123474a4d8c2SCharles.Forsyth 	case AFCMPEF:	return OPF2(85);
123574a4d8c2SCharles.Forsyth 	case AFCMPED:	return OPF2(86);
123674a4d8c2SCharles.Forsyth 	case AFCMPEX:	return OPF2(87);
123774a4d8c2SCharles.Forsyth 
123874a4d8c2SCharles.Forsyth 	case AUNIMP:	return 0;
123974a4d8c2SCharles.Forsyth 	}
124074a4d8c2SCharles.Forsyth 	diag("bad opcode %A", a);
124174a4d8c2SCharles.Forsyth 	return 0;
124274a4d8c2SCharles.Forsyth }
1243