xref: /plan9/sys/src/cmd/5l/asm.c (revision 530fef6600a0fb31e4c0a6ecda1320e97bcd937c)
17dd7cddfSDavid du Colombier #include	"l.h"
27dd7cddfSDavid du Colombier 
37dd7cddfSDavid du Colombier long	OFFSET;
47dd7cddfSDavid du Colombier 
559cc4ca5SDavid du Colombier static Prog *PP;
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier long
87dd7cddfSDavid du Colombier entryvalue(void)
97dd7cddfSDavid du Colombier {
107dd7cddfSDavid du Colombier 	char *a;
117dd7cddfSDavid du Colombier 	Sym *s;
127dd7cddfSDavid du Colombier 
137dd7cddfSDavid du Colombier 	a = INITENTRY;
147dd7cddfSDavid du Colombier 	if(*a >= '0' && *a <= '9')
157dd7cddfSDavid du Colombier 		return atolwhex(a);
167dd7cddfSDavid du Colombier 	s = lookup(a, 0);
177dd7cddfSDavid du Colombier 	if(s->type == 0)
187dd7cddfSDavid du Colombier 		return INITTEXT;
199a747e4fSDavid du Colombier 	switch(s->type) {
209a747e4fSDavid du Colombier 	case STEXT:
219a747e4fSDavid du Colombier 	case SLEAF:
229a747e4fSDavid du Colombier 		break;
239a747e4fSDavid du Colombier 	case SDATA:
24375daca8SDavid du Colombier 		if(dlm)
259a747e4fSDavid du Colombier 			return s->value+INITDAT;
269a747e4fSDavid du Colombier 	default:
277dd7cddfSDavid du Colombier 		diag("entry not text: %s", s->name);
289a747e4fSDavid du Colombier 	}
297dd7cddfSDavid du Colombier 	return s->value;
307dd7cddfSDavid du Colombier }
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier void
337dd7cddfSDavid du Colombier asmb(void)
347dd7cddfSDavid du Colombier {
357dd7cddfSDavid du Colombier 	Prog *p;
369a747e4fSDavid du Colombier 	long t, etext;
377dd7cddfSDavid du Colombier 	Optab *o;
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier 	if(debug['v'])
407dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f asm\n", cputime());
417dd7cddfSDavid du Colombier 	Bflush(&bso);
427dd7cddfSDavid du Colombier 	OFFSET = HEADR;
437dd7cddfSDavid du Colombier 	seek(cout, OFFSET, 0);
447dd7cddfSDavid du Colombier 	pc = INITTEXT;
457dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
467dd7cddfSDavid du Colombier 		if(p->as == ATEXT) {
477dd7cddfSDavid du Colombier 			curtext = p;
487dd7cddfSDavid du Colombier 			autosize = p->to.offset + 4;
497dd7cddfSDavid du Colombier 		}
507dd7cddfSDavid du Colombier 		if(p->pc != pc) {
517dd7cddfSDavid du Colombier 			diag("phase error %lux sb %lux",
527dd7cddfSDavid du Colombier 				p->pc, pc);
537dd7cddfSDavid du Colombier 			if(!debug['a'])
547dd7cddfSDavid du Colombier 				prasm(curp);
557dd7cddfSDavid du Colombier 			pc = p->pc;
567dd7cddfSDavid du Colombier 		}
577dd7cddfSDavid du Colombier 		curp = p;
587dd7cddfSDavid du Colombier 		o = oplook(p);	/* could probably avoid this call */
597dd7cddfSDavid du Colombier 		asmout(p, o);
607dd7cddfSDavid du Colombier 		pc += o->size;
617dd7cddfSDavid du Colombier 	}
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier 	if(debug['a'])
647dd7cddfSDavid du Colombier 		Bprint(&bso, "\n");
657dd7cddfSDavid du Colombier 	Bflush(&bso);
667dd7cddfSDavid du Colombier 	cflush();
677dd7cddfSDavid du Colombier 
689a747e4fSDavid du Colombier 	/* output strings in text segment */
699a747e4fSDavid du Colombier 	etext = INITTEXT + textsize;
709a747e4fSDavid du Colombier 	for(t = pc; t < etext; t += sizeof(buf)-100) {
719a747e4fSDavid du Colombier 		if(etext-t > sizeof(buf)-100)
729a747e4fSDavid du Colombier 			datblk(t, sizeof(buf)-100, 1);
739a747e4fSDavid du Colombier 		else
749a747e4fSDavid du Colombier 			datblk(t, etext-t, 1);
759a747e4fSDavid du Colombier 	}
769a747e4fSDavid du Colombier 
777dd7cddfSDavid du Colombier 	curtext = P;
787dd7cddfSDavid du Colombier 	switch(HEADTYPE) {
7959cc4ca5SDavid du Colombier 	case 0:
807dd7cddfSDavid du Colombier 	case 1:
817dd7cddfSDavid du Colombier 	case 2:
8259cc4ca5SDavid du Colombier 	case 5:
837dd7cddfSDavid du Colombier 		OFFSET = HEADR+textsize;
847dd7cddfSDavid du Colombier 		seek(cout, OFFSET, 0);
857dd7cddfSDavid du Colombier 		break;
867dd7cddfSDavid du Colombier 	case 3:
877dd7cddfSDavid du Colombier 		OFFSET = rnd(HEADR+textsize, 4096);
887dd7cddfSDavid du Colombier 		seek(cout, OFFSET, 0);
897dd7cddfSDavid du Colombier 		break;
907dd7cddfSDavid du Colombier 	}
91375daca8SDavid du Colombier 	if(dlm){
92375daca8SDavid du Colombier 		char buf[8];
93375daca8SDavid du Colombier 
94375daca8SDavid du Colombier 		write(cout, buf, INITDAT-textsize);
95375daca8SDavid du Colombier 		textsize = INITDAT;
96375daca8SDavid du Colombier 	}
977dd7cddfSDavid du Colombier 	for(t = 0; t < datsize; t += sizeof(buf)-100) {
987dd7cddfSDavid du Colombier 		if(datsize-t > sizeof(buf)-100)
999a747e4fSDavid du Colombier 			datblk(t, sizeof(buf)-100, 0);
1007dd7cddfSDavid du Colombier 		else
1019a747e4fSDavid du Colombier 			datblk(t, datsize-t, 0);
1027dd7cddfSDavid du Colombier 	}
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier 	symsize = 0;
1057dd7cddfSDavid du Colombier 	lcsize = 0;
1067dd7cddfSDavid du Colombier 	if(!debug['s']) {
1077dd7cddfSDavid du Colombier 		if(debug['v'])
1087dd7cddfSDavid du Colombier 			Bprint(&bso, "%5.2f sym\n", cputime());
1097dd7cddfSDavid du Colombier 		Bflush(&bso);
1107dd7cddfSDavid du Colombier 		switch(HEADTYPE) {
11159cc4ca5SDavid du Colombier 		case 0:
1127dd7cddfSDavid du Colombier 		case 1:
11359cc4ca5SDavid du Colombier 		case 4:
11459cc4ca5SDavid du Colombier 		case 5:
1157dd7cddfSDavid du Colombier 			debug['s'] = 1;
1167dd7cddfSDavid du Colombier 			break;
1177dd7cddfSDavid du Colombier 		case 2:
1187dd7cddfSDavid du Colombier 			OFFSET = HEADR+textsize+datsize;
1197dd7cddfSDavid du Colombier 			seek(cout, OFFSET, 0);
1207dd7cddfSDavid du Colombier 			break;
1217dd7cddfSDavid du Colombier 		case 3:
1227dd7cddfSDavid du Colombier 			OFFSET += rnd(datsize, 4096);
1237dd7cddfSDavid du Colombier 			seek(cout, OFFSET, 0);
1247dd7cddfSDavid du Colombier 			break;
1257dd7cddfSDavid du Colombier 		}
1267dd7cddfSDavid du Colombier 		if(!debug['s'])
1277dd7cddfSDavid du Colombier 			asmsym();
1287dd7cddfSDavid du Colombier 		if(debug['v'])
1297dd7cddfSDavid du Colombier 			Bprint(&bso, "%5.2f pc\n", cputime());
1307dd7cddfSDavid du Colombier 		Bflush(&bso);
1317dd7cddfSDavid du Colombier 		if(!debug['s'])
1327dd7cddfSDavid du Colombier 			asmlc();
133375daca8SDavid du Colombier 		if(dlm)
134375daca8SDavid du Colombier 			asmdyn();
135375daca8SDavid du Colombier 		cflush();
136375daca8SDavid du Colombier 	}
137375daca8SDavid du Colombier 	else if(dlm){
138375daca8SDavid du Colombier 		seek(cout, HEADR+textsize+datsize, 0);
139375daca8SDavid du Colombier 		asmdyn();
1407dd7cddfSDavid du Colombier 		cflush();
1417dd7cddfSDavid du Colombier 	}
1427dd7cddfSDavid du Colombier 
1437dd7cddfSDavid du Colombier 	if(debug['v'])
1447dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f header\n", cputime());
1457dd7cddfSDavid du Colombier 	Bflush(&bso);
1467dd7cddfSDavid du Colombier 	OFFSET = 0;
1477dd7cddfSDavid du Colombier 	seek(cout, OFFSET, 0);
1487dd7cddfSDavid du Colombier 	switch(HEADTYPE) {
14959cc4ca5SDavid du Colombier 	case 0:	/* no header */
15059cc4ca5SDavid du Colombier 		break;
1517dd7cddfSDavid du Colombier 	case 1:	/* aif for risc os */
1527dd7cddfSDavid du Colombier 		lputl(0xe1a00000);		/* NOP - decompress code */
1537dd7cddfSDavid du Colombier 		lputl(0xe1a00000);		/* NOP - relocation code */
1547dd7cddfSDavid du Colombier 		lputl(0xeb000000 + 12);		/* BL - zero init code */
1557dd7cddfSDavid du Colombier 		lputl(0xeb000000 +
1567dd7cddfSDavid du Colombier 			(entryvalue()
1577dd7cddfSDavid du Colombier 			 - INITTEXT
1587dd7cddfSDavid du Colombier 			 + HEADR
1597dd7cddfSDavid du Colombier 			 - 12
1607dd7cddfSDavid du Colombier 			 - 8) / 4);		/* BL - entry code */
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier 		lputl(0xef000011);		/* SWI - exit code */
1637dd7cddfSDavid du Colombier 		lputl(textsize+HEADR);		/* text size */
1647dd7cddfSDavid du Colombier 		lputl(datsize);			/* data size */
1657dd7cddfSDavid du Colombier 		lputl(0);			/* sym size */
1667dd7cddfSDavid du Colombier 
1677dd7cddfSDavid du Colombier 		lputl(bsssize);			/* bss size */
1687dd7cddfSDavid du Colombier 		lputl(0);			/* sym type */
1697dd7cddfSDavid du Colombier 		lputl(INITTEXT-HEADR);		/* text addr */
1707dd7cddfSDavid du Colombier 		lputl(0);			/* workspace - ignored */
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier 		lputl(32);			/* addr mode / data addr flag */
1737dd7cddfSDavid du Colombier 		lputl(0);			/* data addr */
1747dd7cddfSDavid du Colombier 		for(t=0; t<2; t++)
1757dd7cddfSDavid du Colombier 			lputl(0);		/* reserved */
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier 		for(t=0; t<15; t++)
1787dd7cddfSDavid du Colombier 			lputl(0xe1a00000);	/* NOP - zero init code */
1797dd7cddfSDavid du Colombier 		lputl(0xe1a0f00e);		/* B (R14) - zero init return */
1807dd7cddfSDavid du Colombier 		break;
1817dd7cddfSDavid du Colombier 	case 2:	/* plan 9 */
182375daca8SDavid du Colombier 		if(dlm)
183375daca8SDavid du Colombier 			lput(0x80000000|0x647);	/* magic */
184375daca8SDavid du Colombier 		else
1857dd7cddfSDavid du Colombier 			lput(0x647);			/* magic */
1867dd7cddfSDavid du Colombier 		lput(textsize);			/* sizes */
1877dd7cddfSDavid du Colombier 		lput(datsize);
1887dd7cddfSDavid du Colombier 		lput(bsssize);
1897dd7cddfSDavid du Colombier 		lput(symsize);			/* nsyms */
1907dd7cddfSDavid du Colombier 		lput(entryvalue());		/* va of entry */
1917dd7cddfSDavid du Colombier 		lput(0L);
1927dd7cddfSDavid du Colombier 		lput(lcsize);
1937dd7cddfSDavid du Colombier 		break;
1947dd7cddfSDavid du Colombier 	case 3:	/* boot for NetBSD */
1957dd7cddfSDavid du Colombier 		lput((143<<16)|0413);		/* magic */
1967dd7cddfSDavid du Colombier 		lputl(rnd(HEADR+textsize, 4096));
1977dd7cddfSDavid du Colombier 		lputl(rnd(datsize, 4096));
1987dd7cddfSDavid du Colombier 		lputl(bsssize);
1997dd7cddfSDavid du Colombier 		lputl(symsize);			/* nsyms */
2007dd7cddfSDavid du Colombier 		lputl(entryvalue());		/* va of entry */
2017dd7cddfSDavid du Colombier 		lputl(0L);
2027dd7cddfSDavid du Colombier 		lputl(0L);
2037dd7cddfSDavid du Colombier 		break;
20459cc4ca5SDavid du Colombier 	case 4: /* boot for IXP1200 */
20559cc4ca5SDavid du Colombier 		break;
20659cc4ca5SDavid du Colombier 	case 5: /* boot for ipaq */
20759cc4ca5SDavid du Colombier 		lputl(0xe3300000);		/* nop */
20859cc4ca5SDavid du Colombier 		lputl(0xe3300000);		/* nop */
20959cc4ca5SDavid du Colombier 		lputl(0xe3300000);		/* nop */
21059cc4ca5SDavid du Colombier 		lputl(0xe3300000);		/* nop */
21159cc4ca5SDavid du Colombier 		break;
2127dd7cddfSDavid du Colombier 	}
2137dd7cddfSDavid du Colombier 	cflush();
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier void
2177dd7cddfSDavid du Colombier strnput(char *s, int n)
2187dd7cddfSDavid du Colombier {
2197dd7cddfSDavid du Colombier 	for(; *s; s++){
22059cc4ca5SDavid du Colombier 		cput(*s);
2217dd7cddfSDavid du Colombier 		n--;
2227dd7cddfSDavid du Colombier 	}
2237dd7cddfSDavid du Colombier 	for(; n > 0; n--)
22459cc4ca5SDavid du Colombier 		cput(0);
22559cc4ca5SDavid du Colombier }
22659cc4ca5SDavid du Colombier 
22759cc4ca5SDavid du Colombier void
22859cc4ca5SDavid du Colombier cput(int c)
22959cc4ca5SDavid du Colombier {
23059cc4ca5SDavid du Colombier 	cbp[0] = c;
23159cc4ca5SDavid du Colombier 	cbp++;
23259cc4ca5SDavid du Colombier 	cbc--;
23359cc4ca5SDavid du Colombier 	if(cbc <= 0)
23459cc4ca5SDavid du Colombier 		cflush();
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier void
238375daca8SDavid du Colombier wput(long l)
239375daca8SDavid du Colombier {
240375daca8SDavid du Colombier 
241375daca8SDavid du Colombier 	cbp[0] = l>>8;
242375daca8SDavid du Colombier 	cbp[1] = l;
243375daca8SDavid du Colombier 	cbp += 2;
244375daca8SDavid du Colombier 	cbc -= 2;
245375daca8SDavid du Colombier 	if(cbc <= 0)
246375daca8SDavid du Colombier 		cflush();
247375daca8SDavid du Colombier }
248375daca8SDavid du Colombier 
249375daca8SDavid du Colombier void
2507dd7cddfSDavid du Colombier lput(long l)
2517dd7cddfSDavid du Colombier {
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier 	cbp[0] = l>>24;
2547dd7cddfSDavid du Colombier 	cbp[1] = l>>16;
2557dd7cddfSDavid du Colombier 	cbp[2] = l>>8;
2567dd7cddfSDavid du Colombier 	cbp[3] = l;
2577dd7cddfSDavid du Colombier 	cbp += 4;
2587dd7cddfSDavid du Colombier 	cbc -= 4;
2597dd7cddfSDavid du Colombier 	if(cbc <= 0)
2607dd7cddfSDavid du Colombier 		cflush();
2617dd7cddfSDavid du Colombier }
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier void
2647dd7cddfSDavid du Colombier lputl(long l)
2657dd7cddfSDavid du Colombier {
2667dd7cddfSDavid du Colombier 
2677dd7cddfSDavid du Colombier 	cbp[3] = l>>24;
2687dd7cddfSDavid du Colombier 	cbp[2] = l>>16;
2697dd7cddfSDavid du Colombier 	cbp[1] = l>>8;
2707dd7cddfSDavid du Colombier 	cbp[0] = l;
2717dd7cddfSDavid du Colombier 	cbp += 4;
2727dd7cddfSDavid du Colombier 	cbc -= 4;
2737dd7cddfSDavid du Colombier 	if(cbc <= 0)
2747dd7cddfSDavid du Colombier 		cflush();
2757dd7cddfSDavid du Colombier }
2767dd7cddfSDavid du Colombier 
2777dd7cddfSDavid du Colombier void
2787dd7cddfSDavid du Colombier cflush(void)
2797dd7cddfSDavid du Colombier {
2807dd7cddfSDavid du Colombier 	int n;
2817dd7cddfSDavid du Colombier 
2827dd7cddfSDavid du Colombier 	n = sizeof(buf.cbuf) - cbc;
2837dd7cddfSDavid du Colombier 	if(n)
2847dd7cddfSDavid du Colombier 		write(cout, buf.cbuf, n);
2857dd7cddfSDavid du Colombier 	cbp = buf.cbuf;
2867dd7cddfSDavid du Colombier 	cbc = sizeof(buf.cbuf);
2877dd7cddfSDavid du Colombier }
2887dd7cddfSDavid du Colombier 
2897dd7cddfSDavid du Colombier void
2907dd7cddfSDavid du Colombier nopstat(char *f, Count *c)
2917dd7cddfSDavid du Colombier {
2927dd7cddfSDavid du Colombier 	if(c->outof)
2937dd7cddfSDavid du Colombier 	Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
2947dd7cddfSDavid du Colombier 		c->outof - c->count, c->outof,
2957dd7cddfSDavid du Colombier 		(double)(c->outof - c->count)/c->outof);
2967dd7cddfSDavid du Colombier }
2977dd7cddfSDavid du Colombier 
2987dd7cddfSDavid du Colombier void
2997dd7cddfSDavid du Colombier asmsym(void)
3007dd7cddfSDavid du Colombier {
3017dd7cddfSDavid du Colombier 	Prog *p;
3027dd7cddfSDavid du Colombier 	Auto *a;
3037dd7cddfSDavid du Colombier 	Sym *s;
3047dd7cddfSDavid du Colombier 	int h;
3057dd7cddfSDavid du Colombier 
3067dd7cddfSDavid du Colombier 	s = lookup("etext", 0);
3077dd7cddfSDavid du Colombier 	if(s->type == STEXT)
3087dd7cddfSDavid du Colombier 		putsymb(s->name, 'T', s->value, s->version);
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier 	for(h=0; h<NHASH; h++)
3117dd7cddfSDavid du Colombier 		for(s=hash[h]; s!=S; s=s->link)
3127dd7cddfSDavid du Colombier 			switch(s->type) {
3137dd7cddfSDavid du Colombier 			case SCONST:
3147dd7cddfSDavid du Colombier 				putsymb(s->name, 'D', s->value, s->version);
3157dd7cddfSDavid du Colombier 				continue;
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 			case SDATA:
3187dd7cddfSDavid du Colombier 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
3197dd7cddfSDavid du Colombier 				continue;
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier 			case SBSS:
3227dd7cddfSDavid du Colombier 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
3237dd7cddfSDavid du Colombier 				continue;
3247dd7cddfSDavid du Colombier 
3259a747e4fSDavid du Colombier 			case SSTRING:
3269a747e4fSDavid du Colombier 				putsymb(s->name, 'T', s->value, s->version);
3279a747e4fSDavid du Colombier 				continue;
3289a747e4fSDavid du Colombier 
3297dd7cddfSDavid du Colombier 			case SFILE:
3307dd7cddfSDavid du Colombier 				putsymb(s->name, 'f', s->value, s->version);
3317dd7cddfSDavid du Colombier 				continue;
3327dd7cddfSDavid du Colombier 			}
3337dd7cddfSDavid du Colombier 
3347dd7cddfSDavid du Colombier 	for(p=textp; p!=P; p=p->cond) {
3357dd7cddfSDavid du Colombier 		s = p->from.sym;
3367dd7cddfSDavid du Colombier 		if(s->type != STEXT && s->type != SLEAF)
3377dd7cddfSDavid du Colombier 			continue;
3387dd7cddfSDavid du Colombier 
3397dd7cddfSDavid du Colombier 		/* filenames first */
3407dd7cddfSDavid du Colombier 		for(a=p->to.autom; a; a=a->link)
3417dd7cddfSDavid du Colombier 			if(a->type == D_FILE)
3427dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'z', a->aoffset, 0);
3437dd7cddfSDavid du Colombier 			else
3447dd7cddfSDavid du Colombier 			if(a->type == D_FILE1)
3457dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'Z', a->aoffset, 0);
3467dd7cddfSDavid du Colombier 
3477dd7cddfSDavid du Colombier 		if(s->type == STEXT)
3487dd7cddfSDavid du Colombier 			putsymb(s->name, 'T', s->value, s->version);
3497dd7cddfSDavid du Colombier 		else
3507dd7cddfSDavid du Colombier 			putsymb(s->name, 'L', s->value, s->version);
3517dd7cddfSDavid du Colombier 
3527dd7cddfSDavid du Colombier 		/* frame, auto and param after */
3537dd7cddfSDavid du Colombier 		putsymb(".frame", 'm', p->to.offset+4, 0);
3547dd7cddfSDavid du Colombier 		for(a=p->to.autom; a; a=a->link)
3557dd7cddfSDavid du Colombier 			if(a->type == D_AUTO)
3567dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'a', -a->aoffset, 0);
3577dd7cddfSDavid du Colombier 			else
3587dd7cddfSDavid du Colombier 			if(a->type == D_PARAM)
3597dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'p', a->aoffset, 0);
3607dd7cddfSDavid du Colombier 	}
3617dd7cddfSDavid du Colombier 	if(debug['v'] || debug['n'])
3627dd7cddfSDavid du Colombier 		Bprint(&bso, "symsize = %lud\n", symsize);
3637dd7cddfSDavid du Colombier 	Bflush(&bso);
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier 
3667dd7cddfSDavid du Colombier void
3677dd7cddfSDavid du Colombier putsymb(char *s, int t, long v, int ver)
3687dd7cddfSDavid du Colombier {
3697dd7cddfSDavid du Colombier 	int i, f;
3707dd7cddfSDavid du Colombier 
3717dd7cddfSDavid du Colombier 	if(t == 'f')
3727dd7cddfSDavid du Colombier 		s++;
3737dd7cddfSDavid du Colombier 	lput(v);
3747dd7cddfSDavid du Colombier 	if(ver)
3757dd7cddfSDavid du Colombier 		t += 'a' - 'A';
37659cc4ca5SDavid du Colombier 	cput(t+0x80);			/* 0x80 is variable length */
3777dd7cddfSDavid du Colombier 
3787dd7cddfSDavid du Colombier 	if(t == 'Z' || t == 'z') {
37959cc4ca5SDavid du Colombier 		cput(s[0]);
3807dd7cddfSDavid du Colombier 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
38159cc4ca5SDavid du Colombier 			cput(s[i]);
38259cc4ca5SDavid du Colombier 			cput(s[i+1]);
3837dd7cddfSDavid du Colombier 		}
38459cc4ca5SDavid du Colombier 		cput(0);
38559cc4ca5SDavid du Colombier 		cput(0);
3867dd7cddfSDavid du Colombier 		i++;
3877dd7cddfSDavid du Colombier 	}
3887dd7cddfSDavid du Colombier 	else {
3897dd7cddfSDavid du Colombier 		for(i=0; s[i]; i++)
39059cc4ca5SDavid du Colombier 			cput(s[i]);
39159cc4ca5SDavid du Colombier 		cput(0);
3927dd7cddfSDavid du Colombier 	}
3937dd7cddfSDavid du Colombier 	symsize += 4 + 1 + i + 1;
3947dd7cddfSDavid du Colombier 
3957dd7cddfSDavid du Colombier 	if(debug['n']) {
3967dd7cddfSDavid du Colombier 		if(t == 'z' || t == 'Z') {
3977dd7cddfSDavid du Colombier 			Bprint(&bso, "%c %.8lux ", t, v);
3987dd7cddfSDavid du Colombier 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
3997dd7cddfSDavid du Colombier 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
4007dd7cddfSDavid du Colombier 				Bprint(&bso, "/%x", f);
4017dd7cddfSDavid du Colombier 			}
4027dd7cddfSDavid du Colombier 			Bprint(&bso, "\n");
4037dd7cddfSDavid du Colombier 			return;
4047dd7cddfSDavid du Colombier 		}
4057dd7cddfSDavid du Colombier 		if(ver)
4067dd7cddfSDavid du Colombier 			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
4077dd7cddfSDavid du Colombier 		else
4087dd7cddfSDavid du Colombier 			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
4097dd7cddfSDavid du Colombier 	}
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier 
4127dd7cddfSDavid du Colombier #define	MINLC	4
4137dd7cddfSDavid du Colombier void
4147dd7cddfSDavid du Colombier asmlc(void)
4157dd7cddfSDavid du Colombier {
4167dd7cddfSDavid du Colombier 	long oldpc, oldlc;
4177dd7cddfSDavid du Colombier 	Prog *p;
4187dd7cddfSDavid du Colombier 	long v, s;
4197dd7cddfSDavid du Colombier 
4207dd7cddfSDavid du Colombier 	oldpc = INITTEXT;
4217dd7cddfSDavid du Colombier 	oldlc = 0;
4227dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
4237dd7cddfSDavid du Colombier 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
4247dd7cddfSDavid du Colombier 			if(p->as == ATEXT)
4257dd7cddfSDavid du Colombier 				curtext = p;
4267dd7cddfSDavid du Colombier 			if(debug['L'])
4277dd7cddfSDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
4287dd7cddfSDavid du Colombier 					p->pc, p);
4297dd7cddfSDavid du Colombier 			continue;
4307dd7cddfSDavid du Colombier 		}
4317dd7cddfSDavid du Colombier 		if(debug['L'])
4327dd7cddfSDavid du Colombier 			Bprint(&bso, "\t\t%6ld", lcsize);
4337dd7cddfSDavid du Colombier 		v = (p->pc - oldpc) / MINLC;
4347dd7cddfSDavid du Colombier 		while(v) {
4357dd7cddfSDavid du Colombier 			s = 127;
4367dd7cddfSDavid du Colombier 			if(v < 127)
4377dd7cddfSDavid du Colombier 				s = v;
43859cc4ca5SDavid du Colombier 			cput(s+128);	/* 129-255 +pc */
4397dd7cddfSDavid du Colombier 			if(debug['L'])
4407dd7cddfSDavid du Colombier 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
4417dd7cddfSDavid du Colombier 			v -= s;
4427dd7cddfSDavid du Colombier 			lcsize++;
4437dd7cddfSDavid du Colombier 		}
4447dd7cddfSDavid du Colombier 		s = p->line - oldlc;
4457dd7cddfSDavid du Colombier 		oldlc = p->line;
4467dd7cddfSDavid du Colombier 		oldpc = p->pc + MINLC;
4477dd7cddfSDavid du Colombier 		if(s > 64 || s < -64) {
44859cc4ca5SDavid du Colombier 			cput(0);	/* 0 vv +lc */
44959cc4ca5SDavid du Colombier 			cput(s>>24);
45059cc4ca5SDavid du Colombier 			cput(s>>16);
45159cc4ca5SDavid du Colombier 			cput(s>>8);
45259cc4ca5SDavid du Colombier 			cput(s);
4537dd7cddfSDavid du Colombier 			if(debug['L']) {
4547dd7cddfSDavid du Colombier 				if(s > 0)
4557dd7cddfSDavid du Colombier 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
4567dd7cddfSDavid du Colombier 						s, 0, s);
4577dd7cddfSDavid du Colombier 				else
4587dd7cddfSDavid du Colombier 					Bprint(&bso, " lc%ld(%d,%ld)\n",
4597dd7cddfSDavid du Colombier 						s, 0, s);
4607dd7cddfSDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
4617dd7cddfSDavid du Colombier 					p->pc, p);
4627dd7cddfSDavid du Colombier 			}
4637dd7cddfSDavid du Colombier 			lcsize += 5;
4647dd7cddfSDavid du Colombier 			continue;
4657dd7cddfSDavid du Colombier 		}
4667dd7cddfSDavid du Colombier 		if(s > 0) {
46759cc4ca5SDavid du Colombier 			cput(0+s);	/* 1-64 +lc */
4687dd7cddfSDavid du Colombier 			if(debug['L']) {
4697dd7cddfSDavid du Colombier 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
4707dd7cddfSDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
4717dd7cddfSDavid du Colombier 					p->pc, p);
4727dd7cddfSDavid du Colombier 			}
4737dd7cddfSDavid du Colombier 		} else {
47459cc4ca5SDavid du Colombier 			cput(64-s);	/* 65-128 -lc */
4757dd7cddfSDavid du Colombier 			if(debug['L']) {
4767dd7cddfSDavid du Colombier 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
4777dd7cddfSDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
4787dd7cddfSDavid du Colombier 					p->pc, p);
4797dd7cddfSDavid du Colombier 			}
4807dd7cddfSDavid du Colombier 		}
4817dd7cddfSDavid du Colombier 		lcsize++;
4827dd7cddfSDavid du Colombier 	}
4837dd7cddfSDavid du Colombier 	while(lcsize & 1) {
4847dd7cddfSDavid du Colombier 		s = 129;
48559cc4ca5SDavid du Colombier 		cput(s);
4867dd7cddfSDavid du Colombier 		lcsize++;
4877dd7cddfSDavid du Colombier 	}
4887dd7cddfSDavid du Colombier 	if(debug['v'] || debug['L'])
4897dd7cddfSDavid du Colombier 		Bprint(&bso, "lcsize = %ld\n", lcsize);
4907dd7cddfSDavid du Colombier 	Bflush(&bso);
4917dd7cddfSDavid du Colombier }
4927dd7cddfSDavid du Colombier 
4937dd7cddfSDavid du Colombier void
4949a747e4fSDavid du Colombier datblk(long s, long n, int str)
4957dd7cddfSDavid du Colombier {
4969a747e4fSDavid du Colombier 	Sym *v;
4977dd7cddfSDavid du Colombier 	Prog *p;
4987dd7cddfSDavid du Colombier 	char *cast;
4999a747e4fSDavid du Colombier 	long a, l, fl, j, d;
5007dd7cddfSDavid du Colombier 	int i, c;
5017dd7cddfSDavid du Colombier 
5027dd7cddfSDavid du Colombier 	memset(buf.dbuf, 0, n+100);
5037dd7cddfSDavid du Colombier 	for(p = datap; p != P; p = p->link) {
5049a747e4fSDavid du Colombier 		if(str != (p->from.sym->type == SSTRING))
5059a747e4fSDavid du Colombier 			continue;
5067dd7cddfSDavid du Colombier 		curp = p;
5079a747e4fSDavid du Colombier 		a = p->from.sym->value + p->from.offset;
5089a747e4fSDavid du Colombier 		l = a - s;
5097dd7cddfSDavid du Colombier 		c = p->reg;
5107dd7cddfSDavid du Colombier 		i = 0;
5117dd7cddfSDavid du Colombier 		if(l < 0) {
5127dd7cddfSDavid du Colombier 			if(l+c <= 0)
5137dd7cddfSDavid du Colombier 				continue;
5147dd7cddfSDavid du Colombier 			while(l < 0) {
5157dd7cddfSDavid du Colombier 				l++;
5167dd7cddfSDavid du Colombier 				i++;
5177dd7cddfSDavid du Colombier 			}
5187dd7cddfSDavid du Colombier 		}
5197dd7cddfSDavid du Colombier 		if(l >= n)
5207dd7cddfSDavid du Colombier 			continue;
5217dd7cddfSDavid du Colombier 		if(p->as != AINIT && p->as != ADYNT) {
5227dd7cddfSDavid du Colombier 			for(j=l+(c-i)-1; j>=l; j--)
5237dd7cddfSDavid du Colombier 				if(buf.dbuf[j]) {
5247dd7cddfSDavid du Colombier 					print("%P\n", p);
5257dd7cddfSDavid du Colombier 					diag("multiple initialization");
5267dd7cddfSDavid du Colombier 					break;
5277dd7cddfSDavid du Colombier 				}
5287dd7cddfSDavid du Colombier 		}
5297dd7cddfSDavid du Colombier 		switch(p->to.type) {
5307dd7cddfSDavid du Colombier 		default:
5317dd7cddfSDavid du Colombier 			diag("unknown mode in initialization%P", p);
5327dd7cddfSDavid du Colombier 			break;
5337dd7cddfSDavid du Colombier 
5347dd7cddfSDavid du Colombier 		case D_FCONST:
5357dd7cddfSDavid du Colombier 			switch(c) {
5367dd7cddfSDavid du Colombier 			default:
5377dd7cddfSDavid du Colombier 			case 4:
5387dd7cddfSDavid du Colombier 				fl = ieeedtof(p->to.ieee);
5397dd7cddfSDavid du Colombier 				cast = (char*)&fl;
5407dd7cddfSDavid du Colombier 				for(; i<c; i++) {
5417dd7cddfSDavid du Colombier 					buf.dbuf[l] = cast[fnuxi4[i]];
5427dd7cddfSDavid du Colombier 					l++;
5437dd7cddfSDavid du Colombier 				}
5447dd7cddfSDavid du Colombier 				break;
5457dd7cddfSDavid du Colombier 			case 8:
5467dd7cddfSDavid du Colombier 				cast = (char*)p->to.ieee;
5477dd7cddfSDavid du Colombier 				for(; i<c; i++) {
5487dd7cddfSDavid du Colombier 					buf.dbuf[l] = cast[fnuxi8[i]];
5497dd7cddfSDavid du Colombier 					l++;
5507dd7cddfSDavid du Colombier 				}
5517dd7cddfSDavid du Colombier 				break;
5527dd7cddfSDavid du Colombier 			}
5537dd7cddfSDavid du Colombier 			break;
5547dd7cddfSDavid du Colombier 
5557dd7cddfSDavid du Colombier 		case D_SCONST:
5567dd7cddfSDavid du Colombier 			for(; i<c; i++) {
5577dd7cddfSDavid du Colombier 				buf.dbuf[l] = p->to.sval[i];
5587dd7cddfSDavid du Colombier 				l++;
5597dd7cddfSDavid du Colombier 			}
5607dd7cddfSDavid du Colombier 			break;
5617dd7cddfSDavid du Colombier 
5627dd7cddfSDavid du Colombier 		case D_CONST:
5637dd7cddfSDavid du Colombier 			d = p->to.offset;
5649a747e4fSDavid du Colombier 			v = p->to.sym;
5659a747e4fSDavid du Colombier 			if(v) {
5669a747e4fSDavid du Colombier 				switch(v->type) {
567375daca8SDavid du Colombier 				case SUNDEF:
568375daca8SDavid du Colombier 					ckoff(v, d);
5699a747e4fSDavid du Colombier 				case STEXT:
5709a747e4fSDavid du Colombier 				case SLEAF:
5719a747e4fSDavid du Colombier 				case SSTRING:
5727dd7cddfSDavid du Colombier 					d += p->to.sym->value;
5739a747e4fSDavid du Colombier 					break;
5749a747e4fSDavid du Colombier 				case SDATA:
5759a747e4fSDavid du Colombier 				case SBSS:
5767dd7cddfSDavid du Colombier 					d += p->to.sym->value + INITDAT;
5779a747e4fSDavid du Colombier 				}
578375daca8SDavid du Colombier 				if(dlm)
579375daca8SDavid du Colombier 					dynreloc(v, a+INITDAT, 1);
5807dd7cddfSDavid du Colombier 			}
5817dd7cddfSDavid du Colombier 			cast = (char*)&d;
5827dd7cddfSDavid du Colombier 			switch(c) {
5837dd7cddfSDavid du Colombier 			default:
5847dd7cddfSDavid du Colombier 				diag("bad nuxi %d %d%P", c, i, curp);
5857dd7cddfSDavid du Colombier 				break;
5867dd7cddfSDavid du Colombier 			case 1:
5877dd7cddfSDavid du Colombier 				for(; i<c; i++) {
5887dd7cddfSDavid du Colombier 					buf.dbuf[l] = cast[inuxi1[i]];
5897dd7cddfSDavid du Colombier 					l++;
5907dd7cddfSDavid du Colombier 				}
5917dd7cddfSDavid du Colombier 				break;
5927dd7cddfSDavid du Colombier 			case 2:
5937dd7cddfSDavid du Colombier 				for(; i<c; i++) {
5947dd7cddfSDavid du Colombier 					buf.dbuf[l] = cast[inuxi2[i]];
5957dd7cddfSDavid du Colombier 					l++;
5967dd7cddfSDavid du Colombier 				}
5977dd7cddfSDavid du Colombier 				break;
5987dd7cddfSDavid du Colombier 			case 4:
5997dd7cddfSDavid du Colombier 				for(; i<c; i++) {
6007dd7cddfSDavid du Colombier 					buf.dbuf[l] = cast[inuxi4[i]];
6017dd7cddfSDavid du Colombier 					l++;
6027dd7cddfSDavid du Colombier 				}
6037dd7cddfSDavid du Colombier 				break;
6047dd7cddfSDavid du Colombier 			}
6057dd7cddfSDavid du Colombier 			break;
6067dd7cddfSDavid du Colombier 		}
6077dd7cddfSDavid du Colombier 	}
6087dd7cddfSDavid du Colombier 	write(cout, buf.dbuf, n);
6097dd7cddfSDavid du Colombier }
6107dd7cddfSDavid du Colombier 
6117dd7cddfSDavid du Colombier void
6127dd7cddfSDavid du Colombier asmout(Prog *p, Optab *o)
6137dd7cddfSDavid du Colombier {
61459cc4ca5SDavid du Colombier 	long o1, o2, o3, o4, o5, o6, v;
61559cc4ca5SDavid du Colombier 	int r, rf, rt, rt2;
6169a747e4fSDavid du Colombier 	Sym *s;
6177dd7cddfSDavid du Colombier 
61859cc4ca5SDavid du Colombier PP = p;
6197dd7cddfSDavid du Colombier 	o1 = 0;
6207dd7cddfSDavid du Colombier 	o2 = 0;
6217dd7cddfSDavid du Colombier 	o3 = 0;
6227dd7cddfSDavid du Colombier 	o4 = 0;
6237dd7cddfSDavid du Colombier 	o5 = 0;
62459cc4ca5SDavid du Colombier 	o6 = 0;
6257dd7cddfSDavid du Colombier 	switch(o->type) {
6267dd7cddfSDavid du Colombier 	default:
6277dd7cddfSDavid du Colombier 		diag("unknown asm %d", o->type);
6287dd7cddfSDavid du Colombier 		prasm(p);
6297dd7cddfSDavid du Colombier 		break;
6307dd7cddfSDavid du Colombier 
6317dd7cddfSDavid du Colombier 	case 0:		/* pseudo ops */
6327dd7cddfSDavid du Colombier 		break;
6337dd7cddfSDavid du Colombier 
6347dd7cddfSDavid du Colombier 	case 1:		/* op R,[R],R */
6357dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
6367dd7cddfSDavid du Colombier 		rf = p->from.reg;
6377dd7cddfSDavid du Colombier 		rt = p->to.reg;
6387dd7cddfSDavid du Colombier 		r = p->reg;
6397dd7cddfSDavid du Colombier 		if(p->to.type == D_NONE)
6407dd7cddfSDavid du Colombier 			rt = 0;
641*530fef66SDavid du Colombier 		if(p->as == AMOVW || p->as == AMVN)
642*530fef66SDavid du Colombier 			r = 0;
643*530fef66SDavid du Colombier 		else if(r == NREG)
6447dd7cddfSDavid du Colombier 			r = rt;
6457dd7cddfSDavid du Colombier 		o1 |= rf | (r<<16) | (rt<<12);
6467dd7cddfSDavid du Colombier 		break;
6477dd7cddfSDavid du Colombier 
64859cc4ca5SDavid du Colombier 	case 2:		/* movbu $I,[R],R */
6497dd7cddfSDavid du Colombier 		aclass(&p->from);
6507dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
6517dd7cddfSDavid du Colombier 		o1 |= immrot(instoffset);
6527dd7cddfSDavid du Colombier 		rt = p->to.reg;
6537dd7cddfSDavid du Colombier 		r = p->reg;
6547dd7cddfSDavid du Colombier 		if(p->to.type == D_NONE)
6557dd7cddfSDavid du Colombier 			rt = 0;
656*530fef66SDavid du Colombier 		if(p->as == AMOVW || p->as == AMVN)
657*530fef66SDavid du Colombier 			r = 0;
658*530fef66SDavid du Colombier 		else if(r == NREG)
6597dd7cddfSDavid du Colombier 			r = rt;
6607dd7cddfSDavid du Colombier 		o1 |= (r<<16) | (rt<<12);
6617dd7cddfSDavid du Colombier 		break;
6627dd7cddfSDavid du Colombier 
6637dd7cddfSDavid du Colombier 	case 3:		/* add R<<[IR],[R],R */
66459cc4ca5SDavid du Colombier 	mov:
6657dd7cddfSDavid du Colombier 		aclass(&p->from);
6667dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
6677dd7cddfSDavid du Colombier 		o1 |= p->from.offset;
6687dd7cddfSDavid du Colombier 		rt = p->to.reg;
6697dd7cddfSDavid du Colombier 		r = p->reg;
6707dd7cddfSDavid du Colombier 		if(p->to.type == D_NONE)
6717dd7cddfSDavid du Colombier 			rt = 0;
672*530fef66SDavid du Colombier 		if(p->as == AMOVW || p->as == AMVN)
673*530fef66SDavid du Colombier 			r = 0;
674*530fef66SDavid du Colombier 		else if(r == NREG)
6757dd7cddfSDavid du Colombier 			r = rt;
6767dd7cddfSDavid du Colombier 		o1 |= (r<<16) | (rt<<12);
6777dd7cddfSDavid du Colombier 		break;
6787dd7cddfSDavid du Colombier 
6797dd7cddfSDavid du Colombier 	case 4:		/* add $I,[R],R */
6807dd7cddfSDavid du Colombier 		aclass(&p->from);
6817dd7cddfSDavid du Colombier 		o1 = oprrr(AADD, p->scond);
6827dd7cddfSDavid du Colombier 		o1 |= immrot(instoffset);
6837dd7cddfSDavid du Colombier 		r = p->from.reg;
6847dd7cddfSDavid du Colombier 		if(r == NREG)
6857dd7cddfSDavid du Colombier 			r = o->param;
6867dd7cddfSDavid du Colombier 		o1 |= r << 16;
6877dd7cddfSDavid du Colombier 		o1 |= p->to.reg << 12;
6887dd7cddfSDavid du Colombier 		break;
6897dd7cddfSDavid du Colombier 
6907dd7cddfSDavid du Colombier 	case 5:		/* bra s */
6917dd7cddfSDavid du Colombier 		v = -8;
6929a747e4fSDavid du Colombier 		if(p->cond == UP) {
6939a747e4fSDavid du Colombier 			s = p->to.sym;
694375daca8SDavid du Colombier 			if(s->type != SUNDEF)
695375daca8SDavid du Colombier 				diag("bad branch sym type");
696375daca8SDavid du Colombier 			v = (ulong)s->value >> (Roffset-2);
697375daca8SDavid du Colombier 			dynreloc(s, p->pc, 0);
6989a747e4fSDavid du Colombier 		}
6999a747e4fSDavid du Colombier 		else if(p->cond != P)
7007dd7cddfSDavid du Colombier 			v = (p->cond->pc - pc) - 8;
7017dd7cddfSDavid du Colombier 		o1 = opbra(p->as, p->scond);
7027dd7cddfSDavid du Colombier 		o1 |= (v >> 2) & 0xffffff;
7037dd7cddfSDavid du Colombier 		break;
7047dd7cddfSDavid du Colombier 
7057dd7cddfSDavid du Colombier 	case 6:		/* b ,O(R) -> add $O,R,PC */
7067dd7cddfSDavid du Colombier 		aclass(&p->to);
7077dd7cddfSDavid du Colombier 		o1 = oprrr(AADD, p->scond);
7087dd7cddfSDavid du Colombier 		o1 |= immrot(instoffset);
7097dd7cddfSDavid du Colombier 		o1 |= p->to.reg << 16;
7107dd7cddfSDavid du Colombier 		o1 |= REGPC << 12;
7117dd7cddfSDavid du Colombier 		break;
7127dd7cddfSDavid du Colombier 
7137dd7cddfSDavid du Colombier 	case 7:		/* bl ,O(R) -> mov PC,link; add $O,R,PC */
7147dd7cddfSDavid du Colombier 		aclass(&p->to);
7157dd7cddfSDavid du Colombier 		o1 = oprrr(AADD, p->scond);
7167dd7cddfSDavid du Colombier 		o1 |= immrot(0);
7177dd7cddfSDavid du Colombier 		o1 |= REGPC << 16;
7187dd7cddfSDavid du Colombier 		o1 |= REGLINK << 12;
7197dd7cddfSDavid du Colombier 
7207dd7cddfSDavid du Colombier 		o2 = oprrr(AADD, p->scond);
7217dd7cddfSDavid du Colombier 		o2 |= immrot(instoffset);
7227dd7cddfSDavid du Colombier 		o2 |= p->to.reg << 16;
7237dd7cddfSDavid du Colombier 		o2 |= REGPC << 12;
7247dd7cddfSDavid du Colombier 		break;
7257dd7cddfSDavid du Colombier 
7267dd7cddfSDavid du Colombier 	case 8:		/* sll $c,[R],R -> mov (R<<$c),R */
7277dd7cddfSDavid du Colombier 		aclass(&p->from);
7287dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
7297dd7cddfSDavid du Colombier 		r = p->reg;
7307dd7cddfSDavid du Colombier 		if(r == NREG)
7317dd7cddfSDavid du Colombier 			r = p->to.reg;
7327dd7cddfSDavid du Colombier 		o1 |= r;
7337dd7cddfSDavid du Colombier 		o1 |= (instoffset&31) << 7;
7347dd7cddfSDavid du Colombier 		o1 |= p->to.reg << 12;
7357dd7cddfSDavid du Colombier 		break;
7367dd7cddfSDavid du Colombier 
7377dd7cddfSDavid du Colombier 	case 9:		/* sll R,[R],R -> mov (R<<R),R */
7387dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
7397dd7cddfSDavid du Colombier 		r = p->reg;
7407dd7cddfSDavid du Colombier 		if(r == NREG)
7417dd7cddfSDavid du Colombier 			r = p->to.reg;
7427dd7cddfSDavid du Colombier 		o1 |= r;
7437dd7cddfSDavid du Colombier 		o1 |= (p->from.reg << 8) | (1<<4);
7447dd7cddfSDavid du Colombier 		o1 |= p->to.reg << 12;
7457dd7cddfSDavid du Colombier 		break;
7467dd7cddfSDavid du Colombier 
7477dd7cddfSDavid du Colombier 	case 10:	/* swi [$con] */
7487dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
7497dd7cddfSDavid du Colombier 		if(p->to.type != D_NONE) {
7507dd7cddfSDavid du Colombier 			aclass(&p->to);
7517dd7cddfSDavid du Colombier 			o1 |= instoffset & 0xffffff;
7527dd7cddfSDavid du Colombier 		}
7537dd7cddfSDavid du Colombier 		break;
7547dd7cddfSDavid du Colombier 
7557dd7cddfSDavid du Colombier 	case 11:	/* word */
7569a747e4fSDavid du Colombier 		switch(aclass(&p->to)) {
7579a747e4fSDavid du Colombier 		case C_LCON:
758375daca8SDavid du Colombier 			if(!dlm)
7599a747e4fSDavid du Colombier 				break;
7609a747e4fSDavid du Colombier 			if(p->to.name != D_EXTERN && p->to.name != D_STATIC)
7619a747e4fSDavid du Colombier 				break;
7629a747e4fSDavid du Colombier 		case C_ADDR:
763375daca8SDavid du Colombier 			if(p->to.sym->type == SUNDEF)
764375daca8SDavid du Colombier 				ckoff(p->to.sym, p->to.offset);
765375daca8SDavid du Colombier 			dynreloc(p->to.sym, p->pc, 1);
7669a747e4fSDavid du Colombier 		}
7677dd7cddfSDavid du Colombier 		o1 = instoffset;
7687dd7cddfSDavid du Colombier 		break;
7697dd7cddfSDavid du Colombier 
7707dd7cddfSDavid du Colombier 	case 12:	/* movw $lcon, reg */
77159cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->from, p->to.reg);
7727dd7cddfSDavid du Colombier 		break;
7737dd7cddfSDavid du Colombier 
7747dd7cddfSDavid du Colombier 	case 13:	/* op $lcon, [R], R */
77559cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->from, REGTMP);
77659cc4ca5SDavid du Colombier 		if(!o1)
7777dd7cddfSDavid du Colombier 			break;
7787dd7cddfSDavid du Colombier 		o2 = oprrr(p->as, p->scond);
7797dd7cddfSDavid du Colombier 		o2 |= REGTMP;
7807dd7cddfSDavid du Colombier 		r = p->reg;
781*530fef66SDavid du Colombier 		if(p->as == AMOVW || p->as == AMVN)
782*530fef66SDavid du Colombier 			r = 0;
783*530fef66SDavid du Colombier 		else if(r == NREG)
7847dd7cddfSDavid du Colombier 			r = p->to.reg;
7857dd7cddfSDavid du Colombier 		o2 |= r << 16;
7867dd7cddfSDavid du Colombier 		if(p->to.type != D_NONE)
7877dd7cddfSDavid du Colombier 			o2 |= p->to.reg << 12;
7887dd7cddfSDavid du Colombier 		break;
7897dd7cddfSDavid du Colombier 
7907dd7cddfSDavid du Colombier 	case 14:	/* movb/movbu/movh/movhu R,R */
7917dd7cddfSDavid du Colombier 		o1 = oprrr(ASLL, p->scond);
7927dd7cddfSDavid du Colombier 
7937dd7cddfSDavid du Colombier 		if(p->as == AMOVBU || p->as == AMOVHU)
7947dd7cddfSDavid du Colombier 			o2 = oprrr(ASRL, p->scond);
7957dd7cddfSDavid du Colombier 		else
7967dd7cddfSDavid du Colombier 			o2 = oprrr(ASRA, p->scond);
7977dd7cddfSDavid du Colombier 
7987dd7cddfSDavid du Colombier 		r = p->to.reg;
7997dd7cddfSDavid du Colombier 		o1 |= (p->from.reg)|(r<<12);
8007dd7cddfSDavid du Colombier 		o2 |= (r)|(r<<12);
8017dd7cddfSDavid du Colombier 		if(p->as == AMOVB || p->as == AMOVBU) {
8027dd7cddfSDavid du Colombier 			o1 |= (24<<7);
8037dd7cddfSDavid du Colombier 			o2 |= (24<<7);
8047dd7cddfSDavid du Colombier 		} else {
8057dd7cddfSDavid du Colombier 			o1 |= (16<<7);
8067dd7cddfSDavid du Colombier 			o2 |= (16<<7);
8077dd7cddfSDavid du Colombier 		}
8087dd7cddfSDavid du Colombier 		break;
8097dd7cddfSDavid du Colombier 
8107dd7cddfSDavid du Colombier 	case 15:	/* mul r,[r,]r */
8117dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
8127dd7cddfSDavid du Colombier 		rf = p->from.reg;
8137dd7cddfSDavid du Colombier 		rt = p->to.reg;
8147dd7cddfSDavid du Colombier 		r = p->reg;
8157dd7cddfSDavid du Colombier 		if(r == NREG)
8167dd7cddfSDavid du Colombier 			r = rt;
8177dd7cddfSDavid du Colombier 		if(rt == r) {
8187dd7cddfSDavid du Colombier 			r = rf;
8197dd7cddfSDavid du Colombier 			rf = rt;
8207dd7cddfSDavid du Colombier 		}
8217dd7cddfSDavid du Colombier 		if(0)
8227dd7cddfSDavid du Colombier 		if(rt == r || rf == REGPC || r == REGPC || rt == REGPC) {
8237dd7cddfSDavid du Colombier 			diag("bad registers in MUL");
8247dd7cddfSDavid du Colombier 			prasm(p);
8257dd7cddfSDavid du Colombier 		}
8267dd7cddfSDavid du Colombier 		o1 |= (rf<<8) | r | (rt<<16);
8277dd7cddfSDavid du Colombier 		break;
8287dd7cddfSDavid du Colombier 
8297dd7cddfSDavid du Colombier 
8307dd7cddfSDavid du Colombier 	case 16:	/* div r,[r,]r */
8317dd7cddfSDavid du Colombier 		o1 = 0xf << 28;
8327dd7cddfSDavid du Colombier 		o2 = 0;
8337dd7cddfSDavid du Colombier 		break;
8347dd7cddfSDavid du Colombier 
83559cc4ca5SDavid du Colombier 	case 17:
83659cc4ca5SDavid du Colombier 		o1 = oprrr(p->as, p->scond);
83759cc4ca5SDavid du Colombier 		rf = p->from.reg;
83859cc4ca5SDavid du Colombier 		rt = p->to.reg;
83959cc4ca5SDavid du Colombier 		rt2 = p->to.offset;
84059cc4ca5SDavid du Colombier 		r = p->reg;
84159cc4ca5SDavid du Colombier 		o1 |= (rf<<8) | r | (rt<<16) | (rt2<<12);
84259cc4ca5SDavid du Colombier 		break;
84359cc4ca5SDavid du Colombier 
8447dd7cddfSDavid du Colombier 	case 20:	/* mov/movb/movbu R,O(R) */
8457dd7cddfSDavid du Colombier 		aclass(&p->to);
8467dd7cddfSDavid du Colombier 		r = p->to.reg;
8477dd7cddfSDavid du Colombier 		if(r == NREG)
8487dd7cddfSDavid du Colombier 			r = o->param;
8497dd7cddfSDavid du Colombier 		o1 = osr(p->as, p->from.reg, instoffset, r, p->scond);
8507dd7cddfSDavid du Colombier 		break;
8517dd7cddfSDavid du Colombier 
8527dd7cddfSDavid du Colombier 	case 21:	/* mov/movbu O(R),R -> lr */
8537dd7cddfSDavid du Colombier 		aclass(&p->from);
8547dd7cddfSDavid du Colombier 		r = p->from.reg;
8557dd7cddfSDavid du Colombier 		if(r == NREG)
8567dd7cddfSDavid du Colombier 			r = o->param;
8577dd7cddfSDavid du Colombier 		o1 = olr(instoffset, r, p->to.reg, p->scond);
8587dd7cddfSDavid du Colombier 		if(p->as != AMOVW)
8597dd7cddfSDavid du Colombier 			o1 |= 1<<22;
8607dd7cddfSDavid du Colombier 		break;
8617dd7cddfSDavid du Colombier 
8627dd7cddfSDavid du Colombier 	case 22:	/* movb/movh/movhu O(R),R -> lr,shl,shr */
8637dd7cddfSDavid du Colombier 		aclass(&p->from);
8647dd7cddfSDavid du Colombier 		r = p->from.reg;
8657dd7cddfSDavid du Colombier 		if(r == NREG)
8667dd7cddfSDavid du Colombier 			r = o->param;
8677dd7cddfSDavid du Colombier 		o1 = olr(instoffset, r, p->to.reg, p->scond);
8687dd7cddfSDavid du Colombier 
8697dd7cddfSDavid du Colombier 		o2 = oprrr(ASLL, p->scond);
8707dd7cddfSDavid du Colombier 		o3 = oprrr(ASRA, p->scond);
8717dd7cddfSDavid du Colombier 		r = p->to.reg;
8727dd7cddfSDavid du Colombier 		if(p->as == AMOVB) {
8737dd7cddfSDavid du Colombier 			o2 |= (24<<7)|(r)|(r<<12);
8747dd7cddfSDavid du Colombier 			o3 |= (24<<7)|(r)|(r<<12);
8757dd7cddfSDavid du Colombier 		} else {
8767dd7cddfSDavid du Colombier 			o2 |= (16<<7)|(r)|(r<<12);
8777dd7cddfSDavid du Colombier 			if(p->as == AMOVHU)
8787dd7cddfSDavid du Colombier 				o3 = oprrr(ASRL, p->scond);
8797dd7cddfSDavid du Colombier 			o3 |= (16<<7)|(r)|(r<<12);
8807dd7cddfSDavid du Colombier 		}
8817dd7cddfSDavid du Colombier 		break;
8827dd7cddfSDavid du Colombier 
8837dd7cddfSDavid du Colombier 	case 23:	/* movh/movhu R,O(R) -> sb,sb */
8847dd7cddfSDavid du Colombier 		aclass(&p->to);
8857dd7cddfSDavid du Colombier 		r = p->to.reg;
8867dd7cddfSDavid du Colombier 		if(r == NREG)
8877dd7cddfSDavid du Colombier 			r = o->param;
8887dd7cddfSDavid du Colombier 		o1 = osr(AMOVH, p->from.reg, instoffset, r, p->scond);
8897dd7cddfSDavid du Colombier 
8907dd7cddfSDavid du Colombier 		o2 = oprrr(ASRL, p->scond);
8917dd7cddfSDavid du Colombier 		o2 |= (8<<7)|(p->from.reg)|(REGTMP<<12);
8927dd7cddfSDavid du Colombier 
8937dd7cddfSDavid du Colombier 		o3 = osr(AMOVH, REGTMP, instoffset+1, r, p->scond);
8947dd7cddfSDavid du Colombier 		break;
8957dd7cddfSDavid du Colombier 
8967dd7cddfSDavid du Colombier 	case 30:	/* mov/movb/movbu R,L(R) */
89759cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->to, REGTMP);
89859cc4ca5SDavid du Colombier 		if(!o1)
8997dd7cddfSDavid du Colombier 			break;
9007dd7cddfSDavid du Colombier 		r = p->to.reg;
9017dd7cddfSDavid du Colombier 		if(r == NREG)
9027dd7cddfSDavid du Colombier 			r = o->param;
9037dd7cddfSDavid du Colombier 		o2 = osrr(p->from.reg, REGTMP,r, p->scond);
9047dd7cddfSDavid du Colombier 		if(p->as != AMOVW)
9057dd7cddfSDavid du Colombier 			o2 |= 1<<22;
9067dd7cddfSDavid du Colombier 		break;
9077dd7cddfSDavid du Colombier 
9087dd7cddfSDavid du Colombier 	case 31:	/* mov/movbu L(R),R -> lr[b] */
9097dd7cddfSDavid du Colombier 	case 32:	/* movh/movb L(R),R -> lr[b] */
91059cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->from, REGTMP);
91159cc4ca5SDavid du Colombier 		if(!o1)
9127dd7cddfSDavid du Colombier 			break;
9137dd7cddfSDavid du Colombier 		r = p->from.reg;
9147dd7cddfSDavid du Colombier 		if(r == NREG)
9157dd7cddfSDavid du Colombier 			r = o->param;
9167dd7cddfSDavid du Colombier 		o2 = olrr(REGTMP,r, p->to.reg, p->scond);
91759cc4ca5SDavid du Colombier 		if(p->as == AMOVBU || p->as == AMOVB)
9187dd7cddfSDavid du Colombier 			o2 |= 1<<22;
9197dd7cddfSDavid du Colombier 		if(o->type == 31)
9207dd7cddfSDavid du Colombier 			break;
9217dd7cddfSDavid du Colombier 
9227dd7cddfSDavid du Colombier 		o3 = oprrr(ASLL, p->scond);
9237dd7cddfSDavid du Colombier 
9247dd7cddfSDavid du Colombier 		if(p->as == AMOVBU || p->as == AMOVHU)
9257dd7cddfSDavid du Colombier 			o4 = oprrr(ASRL, p->scond);
9267dd7cddfSDavid du Colombier 		else
9277dd7cddfSDavid du Colombier 			o4 = oprrr(ASRA, p->scond);
9287dd7cddfSDavid du Colombier 
9297dd7cddfSDavid du Colombier 		r = p->to.reg;
9307dd7cddfSDavid du Colombier 		o3 |= (r)|(r<<12);
9317dd7cddfSDavid du Colombier 		o4 |= (r)|(r<<12);
9327dd7cddfSDavid du Colombier 		if(p->as == AMOVB || p->as == AMOVBU) {
9337dd7cddfSDavid du Colombier 			o3 |= (24<<7);
9347dd7cddfSDavid du Colombier 			o4 |= (24<<7);
9357dd7cddfSDavid du Colombier 		} else {
9367dd7cddfSDavid du Colombier 			o3 |= (16<<7);
9377dd7cddfSDavid du Colombier 			o4 |= (16<<7);
9387dd7cddfSDavid du Colombier 		}
9397dd7cddfSDavid du Colombier 		break;
9407dd7cddfSDavid du Colombier 
94159cc4ca5SDavid du Colombier 	case 33:	/* movh/movhu R,L(R) -> sb, sb */
94259cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->to, REGTMP);
94359cc4ca5SDavid du Colombier 		if(!o1)
9447dd7cddfSDavid du Colombier 			break;
9457dd7cddfSDavid du Colombier 		r = p->to.reg;
9467dd7cddfSDavid du Colombier 		if(r == NREG)
9477dd7cddfSDavid du Colombier 			r = o->param;
94859cc4ca5SDavid du Colombier 		o2 = osrr(p->from.reg, REGTMP, r, p->scond);
94959cc4ca5SDavid du Colombier 		o2 |= (1<<22) ;
95059cc4ca5SDavid du Colombier 
95159cc4ca5SDavid du Colombier 		o3 = oprrr(ASRL, p->scond);
95259cc4ca5SDavid du Colombier 		o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12);
95359cc4ca5SDavid du Colombier 		o3 |= (1<<6);	/* ROR 8 */
95459cc4ca5SDavid du Colombier 
95559cc4ca5SDavid du Colombier 		o4 = oprrr(AADD, p->scond);
95659cc4ca5SDavid du Colombier 		o4 |= (REGTMP << 12) | (REGTMP << 16);
95759cc4ca5SDavid du Colombier 		o4 |= immrot(1);
95859cc4ca5SDavid du Colombier 
95959cc4ca5SDavid du Colombier 		o5 = osrr(p->from.reg, REGTMP,r,p->scond);
96059cc4ca5SDavid du Colombier 		o5 |= (1<<22);
96159cc4ca5SDavid du Colombier 
96259cc4ca5SDavid du Colombier 		o6 = oprrr(ASRL, p->scond);
96359cc4ca5SDavid du Colombier 		o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12);
96459cc4ca5SDavid du Colombier 		o6 |= (1<<6);	/* ROL 8 */
96559cc4ca5SDavid du Colombier 
9667dd7cddfSDavid du Colombier 		break;
9677dd7cddfSDavid du Colombier 
9687dd7cddfSDavid du Colombier 	case 34:	/* mov $lacon,R */
96959cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->from, REGTMP);
97059cc4ca5SDavid du Colombier 		if(!o1)
9717dd7cddfSDavid du Colombier 			break;
9727dd7cddfSDavid du Colombier 
9737dd7cddfSDavid du Colombier 		o2 = oprrr(AADD, p->scond);
9747dd7cddfSDavid du Colombier 		o2 |= REGTMP;
97580ee5cbfSDavid du Colombier 		r = p->from.reg;
9767dd7cddfSDavid du Colombier 		if(r == NREG)
9777dd7cddfSDavid du Colombier 			r = o->param;
9787dd7cddfSDavid du Colombier 		o2 |= r << 16;
9797dd7cddfSDavid du Colombier 		if(p->to.type != D_NONE)
9807dd7cddfSDavid du Colombier 			o2 |= p->to.reg << 12;
9817dd7cddfSDavid du Colombier 		break;
9827dd7cddfSDavid du Colombier 
9837dd7cddfSDavid du Colombier 	case 35:	/* mov PSR,R */
9847dd7cddfSDavid du Colombier 		o1 = (2<<23) | (0xf<<16) | (0<<0);
9857dd7cddfSDavid du Colombier 		o1 |= (p->scond & C_SCOND) << 28;
9867dd7cddfSDavid du Colombier 		o1 |= (p->from.reg & 1) << 22;
9877dd7cddfSDavid du Colombier 		o1 |= p->to.reg << 12;
9887dd7cddfSDavid du Colombier 		break;
9897dd7cddfSDavid du Colombier 
9907dd7cddfSDavid du Colombier 	case 36:	/* mov R,PSR */
9917dd7cddfSDavid du Colombier 		o1 = (2<<23) | (0x29f<<12) | (0<<4);
9927dd7cddfSDavid du Colombier 		if(p->scond & C_FBIT)
9937dd7cddfSDavid du Colombier 			o1 ^= 0x010 << 12;
9947dd7cddfSDavid du Colombier 		o1 |= (p->scond & C_SCOND) << 28;
9957dd7cddfSDavid du Colombier 		o1 |= (p->to.reg & 1) << 22;
9967dd7cddfSDavid du Colombier 		o1 |= p->from.reg << 0;
9977dd7cddfSDavid du Colombier 		break;
9987dd7cddfSDavid du Colombier 
9997dd7cddfSDavid du Colombier 	case 37:	/* mov $con,PSR */
10007dd7cddfSDavid du Colombier 		aclass(&p->from);
10017dd7cddfSDavid du Colombier 		o1 = (2<<23) | (0x29f<<12) | (0<<4);
10027dd7cddfSDavid du Colombier 		if(p->scond & C_FBIT)
10037dd7cddfSDavid du Colombier 			o1 ^= 0x010 << 12;
10047dd7cddfSDavid du Colombier 		o1 |= (p->scond & C_SCOND) << 28;
10057dd7cddfSDavid du Colombier 		o1 |= immrot(instoffset);
10067dd7cddfSDavid du Colombier 		o1 |= (p->to.reg & 1) << 22;
10077dd7cddfSDavid du Colombier 		o1 |= p->from.reg << 0;
10087dd7cddfSDavid du Colombier 		break;
10097dd7cddfSDavid du Colombier 
10107dd7cddfSDavid du Colombier 	case 38:	/* movm $con,oreg -> stm */
10117dd7cddfSDavid du Colombier 		o1 = (0x4 << 25);
10127dd7cddfSDavid du Colombier 		o1 |= p->from.offset & 0xffff;
10137dd7cddfSDavid du Colombier 		o1 |= p->to.reg << 16;
10147dd7cddfSDavid du Colombier 		aclass(&p->to);
10157dd7cddfSDavid du Colombier 		goto movm;
10167dd7cddfSDavid du Colombier 
10177dd7cddfSDavid du Colombier 	case 39:	/* movm oreg,$con -> ldm */
10187dd7cddfSDavid du Colombier 		o1 = (0x4 << 25) | (1 << 20);
10197dd7cddfSDavid du Colombier 		o1 |= p->to.offset & 0xffff;
10207dd7cddfSDavid du Colombier 		o1 |= p->from.reg << 16;
10217dd7cddfSDavid du Colombier 		aclass(&p->from);
10227dd7cddfSDavid du Colombier 	movm:
10237dd7cddfSDavid du Colombier 		if(instoffset != 0)
10247dd7cddfSDavid du Colombier 			diag("offset must be zero in MOVM");
10257dd7cddfSDavid du Colombier 		o1 |= (p->scond & C_SCOND) << 28;
10267dd7cddfSDavid du Colombier 		if(p->scond & C_PBIT)
10277dd7cddfSDavid du Colombier 			o1 |= 1 << 24;
10287dd7cddfSDavid du Colombier 		if(p->scond & C_UBIT)
10297dd7cddfSDavid du Colombier 			o1 |= 1 << 23;
10307dd7cddfSDavid du Colombier 		if(p->scond & C_SBIT)
10317dd7cddfSDavid du Colombier 			o1 |= 1 << 22;
10327dd7cddfSDavid du Colombier 		if(p->scond & C_WBIT)
10337dd7cddfSDavid du Colombier 			o1 |= 1 << 21;
10347dd7cddfSDavid du Colombier 		break;
10357dd7cddfSDavid du Colombier 
10367dd7cddfSDavid du Colombier 	case 40:	/* swp oreg,reg,reg */
10377dd7cddfSDavid du Colombier 		aclass(&p->from);
10387dd7cddfSDavid du Colombier 		if(instoffset != 0)
10397dd7cddfSDavid du Colombier 			diag("offset must be zero in SWP");
10407dd7cddfSDavid du Colombier 		o1 = (0x2<<23) | (0x9<<4);
10417dd7cddfSDavid du Colombier 		if(p->as != ASWPW)
10427dd7cddfSDavid du Colombier 			o1 |= 1 << 22;
10437dd7cddfSDavid du Colombier 		o1 |= p->from.reg << 16;
10447dd7cddfSDavid du Colombier 		o1 |= p->reg << 0;
10457dd7cddfSDavid du Colombier 		o1 |= p->to.reg << 12;
10467dd7cddfSDavid du Colombier 		o1 |= (p->scond & C_SCOND) << 28;
10477dd7cddfSDavid du Colombier 		break;
10487dd7cddfSDavid du Colombier 
10497dd7cddfSDavid du Colombier 	case 41:	/* rfe -> movm.s.w.u 0(r13),[r15] */
10507dd7cddfSDavid du Colombier 		o1 = 0xe8fd8000;
10517dd7cddfSDavid du Colombier 		break;
10527dd7cddfSDavid du Colombier 
10537dd7cddfSDavid du Colombier 	case 50:	/* floating point store */
10547dd7cddfSDavid du Colombier 		v = regoff(&p->to);
10557dd7cddfSDavid du Colombier 		r = p->to.reg;
10567dd7cddfSDavid du Colombier 		if(r == NREG)
10577dd7cddfSDavid du Colombier 			r = o->param;
105859cc4ca5SDavid du Colombier 		o1 = ofsr(p->as, p->from.reg, v, r, p->scond, p);
10597dd7cddfSDavid du Colombier 		break;
10607dd7cddfSDavid du Colombier 
10617dd7cddfSDavid du Colombier 	case 51:	/* floating point load */
10627dd7cddfSDavid du Colombier 		v = regoff(&p->from);
10637dd7cddfSDavid du Colombier 		r = p->from.reg;
10647dd7cddfSDavid du Colombier 		if(r == NREG)
10657dd7cddfSDavid du Colombier 			r = o->param;
106659cc4ca5SDavid du Colombier 		o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<20);
10677dd7cddfSDavid du Colombier 		break;
10687dd7cddfSDavid du Colombier 
10697dd7cddfSDavid du Colombier 	case 52:	/* floating point store, long offset UGLY */
107059cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->to, REGTMP);
107159cc4ca5SDavid du Colombier 		if(!o1)
10727dd7cddfSDavid du Colombier 			break;
10737dd7cddfSDavid du Colombier 		r = p->to.reg;
10747dd7cddfSDavid du Colombier 		if(r == NREG)
10757dd7cddfSDavid du Colombier 			r = o->param;
10767dd7cddfSDavid du Colombier 		o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r;
107759cc4ca5SDavid du Colombier 		o3 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
10787dd7cddfSDavid du Colombier 		break;
10797dd7cddfSDavid du Colombier 
10807dd7cddfSDavid du Colombier 	case 53:	/* floating point load, long offset UGLY */
108159cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->from, REGTMP);
108259cc4ca5SDavid du Colombier 		if(!o1)
10837dd7cddfSDavid du Colombier 			break;
10847dd7cddfSDavid du Colombier 		r = p->from.reg;
10857dd7cddfSDavid du Colombier 		if(r == NREG)
10867dd7cddfSDavid du Colombier 			r = o->param;
10877dd7cddfSDavid du Colombier 		o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r;
108859cc4ca5SDavid du Colombier 		o3 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
10897dd7cddfSDavid du Colombier 		break;
10907dd7cddfSDavid du Colombier 
10917dd7cddfSDavid du Colombier 	case 54:	/* floating point arith */
10927dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
10937dd7cddfSDavid du Colombier 		if(p->from.type == D_FCONST) {
10947dd7cddfSDavid du Colombier 			rf = chipfloat(p->from.ieee);
10957dd7cddfSDavid du Colombier 			if(rf < 0){
10967dd7cddfSDavid du Colombier 				diag("invalid floating-point immediate\n%P", p);
10977dd7cddfSDavid du Colombier 				rf = 0;
10987dd7cddfSDavid du Colombier 			}
10997dd7cddfSDavid du Colombier 			rf |= (1<<3);
11007dd7cddfSDavid du Colombier 		} else
11017dd7cddfSDavid du Colombier 			rf = p->from.reg;
11027dd7cddfSDavid du Colombier 		rt = p->to.reg;
11037dd7cddfSDavid du Colombier 		r = p->reg;
11047dd7cddfSDavid du Colombier 		if(p->to.type == D_NONE)
11057dd7cddfSDavid du Colombier 			rt = 0;	/* CMP[FD] */
11067dd7cddfSDavid du Colombier 		else if(o1 & (1<<15))
11077dd7cddfSDavid du Colombier 			r = 0;	/* monadic */
11087dd7cddfSDavid du Colombier 		else if(r == NREG)
11097dd7cddfSDavid du Colombier 			r = rt;
11107dd7cddfSDavid du Colombier 		o1 |= rf | (r<<16) | (rt<<12);
11117dd7cddfSDavid du Colombier 		break;
11127dd7cddfSDavid du Colombier 
11137dd7cddfSDavid du Colombier 	case 55:	/* floating point fix and float */
11147dd7cddfSDavid du Colombier 		o1 = oprrr(p->as, p->scond);
11157dd7cddfSDavid du Colombier 		rf = p->from.reg;
11167dd7cddfSDavid du Colombier 		rt = p->to.reg;
11177dd7cddfSDavid du Colombier 		if(p->to.type == D_NONE){
11187dd7cddfSDavid du Colombier 			rt = 0;
11197dd7cddfSDavid du Colombier 			diag("to.type==D_NONE (asm/fp)");
11207dd7cddfSDavid du Colombier 		}
11217dd7cddfSDavid du Colombier 		if(p->from.type == D_REG)
11227dd7cddfSDavid du Colombier 			o1 |= (rf<<12) | (rt<<16);
11237dd7cddfSDavid du Colombier 		else
11247dd7cddfSDavid du Colombier 			o1 |= rf | (rt<<12);
11257dd7cddfSDavid du Colombier 		break;
11267dd7cddfSDavid du Colombier 
11277dd7cddfSDavid du Colombier 	case 56:	/* move to FP[CS]R */
11287dd7cddfSDavid du Colombier 		o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
11297dd7cddfSDavid du Colombier 		o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12);
11307dd7cddfSDavid du Colombier 		break;
11317dd7cddfSDavid du Colombier 
11327dd7cddfSDavid du Colombier 	case 57:	/* move from FP[CS]R */
11337dd7cddfSDavid du Colombier 		o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
11347dd7cddfSDavid du Colombier 		o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20);
11357dd7cddfSDavid du Colombier 		break;
113659cc4ca5SDavid du Colombier 	case 58:	/* movbu R,R */
11377dd7cddfSDavid du Colombier 		o1 = oprrr(AAND, p->scond);
11387dd7cddfSDavid du Colombier 		o1 |= immrot(0xff);
11397dd7cddfSDavid du Colombier 		rt = p->to.reg;
11407dd7cddfSDavid du Colombier 		r = p->from.reg;
11417dd7cddfSDavid du Colombier 		if(p->to.type == D_NONE)
11427dd7cddfSDavid du Colombier 			rt = 0;
11437dd7cddfSDavid du Colombier 		if(r == NREG)
11447dd7cddfSDavid du Colombier 			r = rt;
11457dd7cddfSDavid du Colombier 		o1 |= (r<<16) | (rt<<12);
11467dd7cddfSDavid du Colombier 		break;
114759cc4ca5SDavid du Colombier 
114859cc4ca5SDavid du Colombier 	case 59:	/* movw/bu R<<I(R),R -> ldr indexed */
114959cc4ca5SDavid du Colombier 		if(p->from.reg == NREG) {
115059cc4ca5SDavid du Colombier 			if(p->as != AMOVW)
115159cc4ca5SDavid du Colombier 				diag("byte MOV from shifter operand");
115259cc4ca5SDavid du Colombier 			goto mov;
115359cc4ca5SDavid du Colombier 		}
115459cc4ca5SDavid du Colombier 		if(p->from.offset&(1<<4))
115559cc4ca5SDavid du Colombier 			diag("bad shift in LDR");
115659cc4ca5SDavid du Colombier 		o1 = olrr(p->from.offset, p->from.reg, p->to.reg, p->scond);
115759cc4ca5SDavid du Colombier 		if(p->as == AMOVBU)
115859cc4ca5SDavid du Colombier 			o1 |= 1<<22;
115959cc4ca5SDavid du Colombier 		break;
116059cc4ca5SDavid du Colombier 
116159cc4ca5SDavid du Colombier 	case 60:	/* movb R(R),R -> ldrsb indexed */
116259cc4ca5SDavid du Colombier 		if(p->from.reg == NREG) {
116359cc4ca5SDavid du Colombier 			diag("byte MOV from shifter operand");
116459cc4ca5SDavid du Colombier 			goto mov;
116559cc4ca5SDavid du Colombier 		}
116659cc4ca5SDavid du Colombier 		if(p->from.offset&(~0xf))
116759cc4ca5SDavid du Colombier 			diag("bad shift in LDRSB");
116859cc4ca5SDavid du Colombier 		o1 = olhrr(p->from.offset, p->from.reg, p->to.reg, p->scond);
116959cc4ca5SDavid du Colombier 		o1 ^= (1<<5)|(1<<6);
117059cc4ca5SDavid du Colombier 		break;
117159cc4ca5SDavid du Colombier 
117259cc4ca5SDavid du Colombier 	case 61:	/* movw/b/bu R,R<<[IR](R) -> str indexed */
117359cc4ca5SDavid du Colombier 		if(p->to.reg == NREG)
117459cc4ca5SDavid du Colombier 			diag("MOV to shifter operand");
117559cc4ca5SDavid du Colombier 		o1 = osrr(p->from.reg, p->to.offset, p->to.reg, p->scond);
117659cc4ca5SDavid du Colombier 		if(p->as == AMOVB || p->as == AMOVBU)
117759cc4ca5SDavid du Colombier 			o1 |= 1<<22;
117859cc4ca5SDavid du Colombier 		break;
117959cc4ca5SDavid du Colombier 
118059cc4ca5SDavid du Colombier 	case 62:	/* case R -> movw	R<<2(PC),PC */
118159cc4ca5SDavid du Colombier 		o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
118259cc4ca5SDavid du Colombier 		o1 |= 2<<7;
118359cc4ca5SDavid du Colombier 		break;
118459cc4ca5SDavid du Colombier 
118559cc4ca5SDavid du Colombier 	case 63:	/* bcase */
11869a747e4fSDavid du Colombier 		if(p->cond != P) {
118759cc4ca5SDavid du Colombier 			o1 = p->cond->pc;
1188375daca8SDavid du Colombier 			if(dlm)
1189375daca8SDavid du Colombier 				dynreloc(S, p->pc, 1);
11909a747e4fSDavid du Colombier 		}
11919a747e4fSDavid du Colombier 		break;
11929a747e4fSDavid du Colombier 
11939a747e4fSDavid du Colombier 	/* reloc ops */
11949a747e4fSDavid du Colombier 	case 64:	/* mov/movb/movbu R,addr */
11959a747e4fSDavid du Colombier 		o1 = omvl(p, &p->to, REGTMP);
11969a747e4fSDavid du Colombier 		if(!o1)
11979a747e4fSDavid du Colombier 			break;
11989a747e4fSDavid du Colombier 		o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
11999a747e4fSDavid du Colombier 		break;
12009a747e4fSDavid du Colombier 
12019a747e4fSDavid du Colombier 	case 65:	/* mov/movbu addr,R */
12029a747e4fSDavid du Colombier 	case 66:	/* movh/movhu/movb addr,R */
12039a747e4fSDavid du Colombier 		o1 = omvl(p, &p->from, REGTMP);
12049a747e4fSDavid du Colombier 		if(!o1)
12059a747e4fSDavid du Colombier 			break;
12069a747e4fSDavid du Colombier 		o2 = olr(0, REGTMP, p->to.reg, p->scond);
12079a747e4fSDavid du Colombier 		if(p->as == AMOVBU || p->as == AMOVB)
12089a747e4fSDavid du Colombier 			o2 |= 1<<22;
12099a747e4fSDavid du Colombier 		if(o->type == 65)
12109a747e4fSDavid du Colombier 			break;
12119a747e4fSDavid du Colombier 
12129a747e4fSDavid du Colombier 		o3 = oprrr(ASLL, p->scond);
12139a747e4fSDavid du Colombier 
12149a747e4fSDavid du Colombier 		if(p->as == AMOVBU || p->as == AMOVHU)
12159a747e4fSDavid du Colombier 			o4 = oprrr(ASRL, p->scond);
12169a747e4fSDavid du Colombier 		else
12179a747e4fSDavid du Colombier 			o4 = oprrr(ASRA, p->scond);
12189a747e4fSDavid du Colombier 
12199a747e4fSDavid du Colombier 		r = p->to.reg;
12209a747e4fSDavid du Colombier 		o3 |= (r)|(r<<12);
12219a747e4fSDavid du Colombier 		o4 |= (r)|(r<<12);
12229a747e4fSDavid du Colombier 		if(p->as == AMOVB || p->as == AMOVBU) {
12239a747e4fSDavid du Colombier 			o3 |= (24<<7);
12249a747e4fSDavid du Colombier 			o4 |= (24<<7);
12259a747e4fSDavid du Colombier 		} else {
12269a747e4fSDavid du Colombier 			o3 |= (16<<7);
12279a747e4fSDavid du Colombier 			o4 |= (16<<7);
12289a747e4fSDavid du Colombier 		}
12299a747e4fSDavid du Colombier 		break;
12309a747e4fSDavid du Colombier 
12319a747e4fSDavid du Colombier 	case 67:	/* movh/movhu R,addr -> sb, sb */
12329a747e4fSDavid du Colombier 		o1 = omvl(p, &p->to, REGTMP);
12339a747e4fSDavid du Colombier 		if(!o1)
12349a747e4fSDavid du Colombier 			break;
12359a747e4fSDavid du Colombier 		o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
12369a747e4fSDavid du Colombier 
12379a747e4fSDavid du Colombier 		o3 = oprrr(ASRL, p->scond);
12389a747e4fSDavid du Colombier 		o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12);
12399a747e4fSDavid du Colombier 		o3 |= (1<<6);	/* ROR 8 */
12409a747e4fSDavid du Colombier 
12419a747e4fSDavid du Colombier 		o4 = oprrr(AADD, p->scond);
12429a747e4fSDavid du Colombier 		o4 |= (REGTMP << 12) | (REGTMP << 16);
12439a747e4fSDavid du Colombier 		o4 |= immrot(1);
12449a747e4fSDavid du Colombier 
12459a747e4fSDavid du Colombier 		o5 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
12469a747e4fSDavid du Colombier 
12479a747e4fSDavid du Colombier 		o6 = oprrr(ASRL, p->scond);
12489a747e4fSDavid du Colombier 		o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12);
12499a747e4fSDavid du Colombier 		o6 |= (1<<6);	/* ROL 8 */
12509a747e4fSDavid du Colombier 		break;
12519a747e4fSDavid du Colombier 
12529a747e4fSDavid du Colombier 	case 68:	/* floating point store -> ADDR */
12539a747e4fSDavid du Colombier 		o1 = omvl(p, &p->to, REGTMP);
12549a747e4fSDavid du Colombier 		if(!o1)
12559a747e4fSDavid du Colombier 			break;
12569a747e4fSDavid du Colombier 		o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
12579a747e4fSDavid du Colombier 		break;
12589a747e4fSDavid du Colombier 
12599a747e4fSDavid du Colombier 	case 69:	/* floating point load <- ADDR */
12609a747e4fSDavid du Colombier 		o1 = omvl(p, &p->from, REGTMP);
12619a747e4fSDavid du Colombier 		if(!o1)
12629a747e4fSDavid du Colombier 			break;
12639a747e4fSDavid du Colombier 		o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
126459cc4ca5SDavid du Colombier 		break;
126559cc4ca5SDavid du Colombier 
126659cc4ca5SDavid du Colombier 	/* ArmV4 ops: */
126759cc4ca5SDavid du Colombier 	case 70:	/* movh/movhu R,O(R) -> strh */
126859cc4ca5SDavid du Colombier 		aclass(&p->to);
126959cc4ca5SDavid du Colombier 		r = p->to.reg;
127059cc4ca5SDavid du Colombier 		if(r == NREG)
127159cc4ca5SDavid du Colombier 			r = o->param;
127259cc4ca5SDavid du Colombier 		o1 = oshr(p->from.reg, instoffset, r, p->scond);
127359cc4ca5SDavid du Colombier 		break;
127459cc4ca5SDavid du Colombier 	case 71:	/* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
127559cc4ca5SDavid du Colombier 		aclass(&p->from);
127659cc4ca5SDavid du Colombier 		r = p->from.reg;
127759cc4ca5SDavid du Colombier 		if(r == NREG)
127859cc4ca5SDavid du Colombier 			r = o->param;
127959cc4ca5SDavid du Colombier 		o1 = olhr(instoffset, r, p->to.reg, p->scond);
128059cc4ca5SDavid du Colombier 		if(p->as == AMOVB)
128159cc4ca5SDavid du Colombier 			o1 ^= (1<<5)|(1<<6);
128259cc4ca5SDavid du Colombier 		else if(p->as == AMOVH)
128359cc4ca5SDavid du Colombier 			o1 ^= (1<<6);
128459cc4ca5SDavid du Colombier 		break;
128559cc4ca5SDavid du Colombier 	case 72:	/* movh/movhu R,L(R) -> strh */
128659cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->to, REGTMP);
128759cc4ca5SDavid du Colombier 		if(!o1)
128859cc4ca5SDavid du Colombier 			break;
128959cc4ca5SDavid du Colombier 		r = p->to.reg;
129059cc4ca5SDavid du Colombier 		if(r == NREG)
129159cc4ca5SDavid du Colombier 			r = o->param;
129259cc4ca5SDavid du Colombier 		o2 = oshrr(p->from.reg, REGTMP,r, p->scond);
129359cc4ca5SDavid du Colombier 		break;
129459cc4ca5SDavid du Colombier 	case 73:	/* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
129559cc4ca5SDavid du Colombier 		o1 = omvl(p, &p->from, REGTMP);
129659cc4ca5SDavid du Colombier 		if(!o1)
129759cc4ca5SDavid du Colombier 			break;
129859cc4ca5SDavid du Colombier 		r = p->from.reg;
129959cc4ca5SDavid du Colombier 		if(r == NREG)
130059cc4ca5SDavid du Colombier 			r = o->param;
130159cc4ca5SDavid du Colombier 		o2 = olhrr(REGTMP, r, p->to.reg, p->scond);
130259cc4ca5SDavid du Colombier 		if(p->as == AMOVB)
130359cc4ca5SDavid du Colombier 			o2 ^= (1<<5)|(1<<6);
130459cc4ca5SDavid du Colombier 		else if(p->as == AMOVH)
130559cc4ca5SDavid du Colombier 			o2 ^= (1<<6);
130659cc4ca5SDavid du Colombier 		break;
13077dd7cddfSDavid du Colombier 	}
13087dd7cddfSDavid du Colombier 
13099a747e4fSDavid du Colombier 	if(debug['a'] > 1)
13109a747e4fSDavid du Colombier 		Bprint(&bso, "%2d ", o->type);
13119a747e4fSDavid du Colombier 
13127dd7cddfSDavid du Colombier 	v = p->pc;
13137dd7cddfSDavid du Colombier 	switch(o->size) {
13147dd7cddfSDavid du Colombier 	default:
13157dd7cddfSDavid du Colombier 		if(debug['a'])
13167dd7cddfSDavid du Colombier 			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
13177dd7cddfSDavid du Colombier 		break;
13187dd7cddfSDavid du Colombier 	case 4:
13197dd7cddfSDavid du Colombier 		if(debug['a'])
13207dd7cddfSDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
13217dd7cddfSDavid du Colombier 		lputl(o1);
13227dd7cddfSDavid du Colombier 		break;
13237dd7cddfSDavid du Colombier 	case 8:
13247dd7cddfSDavid du Colombier 		if(debug['a'])
13257dd7cddfSDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
13267dd7cddfSDavid du Colombier 		lputl(o1);
13277dd7cddfSDavid du Colombier 		lputl(o2);
13287dd7cddfSDavid du Colombier 		break;
13297dd7cddfSDavid du Colombier 	case 12:
13307dd7cddfSDavid du Colombier 		if(debug['a'])
13317dd7cddfSDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
13327dd7cddfSDavid du Colombier 		lputl(o1);
13337dd7cddfSDavid du Colombier 		lputl(o2);
13347dd7cddfSDavid du Colombier 		lputl(o3);
13357dd7cddfSDavid du Colombier 		break;
13367dd7cddfSDavid du Colombier 	case 16:
13377dd7cddfSDavid du Colombier 		if(debug['a'])
13387dd7cddfSDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
13397dd7cddfSDavid du Colombier 				v, o1, o2, o3, o4, p);
13407dd7cddfSDavid du Colombier 		lputl(o1);
13417dd7cddfSDavid du Colombier 		lputl(o2);
13427dd7cddfSDavid du Colombier 		lputl(o3);
13437dd7cddfSDavid du Colombier 		lputl(o4);
13447dd7cddfSDavid du Colombier 		break;
13457dd7cddfSDavid du Colombier 	case 20:
13467dd7cddfSDavid du Colombier 		if(debug['a'])
13477dd7cddfSDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
13487dd7cddfSDavid du Colombier 				v, o1, o2, o3, o4, o5, p);
13497dd7cddfSDavid du Colombier 		lputl(o1);
13507dd7cddfSDavid du Colombier 		lputl(o2);
13517dd7cddfSDavid du Colombier 		lputl(o3);
13527dd7cddfSDavid du Colombier 		lputl(o4);
13537dd7cddfSDavid du Colombier 		lputl(o5);
13547dd7cddfSDavid du Colombier 		break;
135559cc4ca5SDavid du Colombier 	case 24:
135659cc4ca5SDavid du Colombier 		if(debug['a'])
135759cc4ca5SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
135859cc4ca5SDavid du Colombier 				v, o1, o2, o3, o4, o5, o6, p);
135959cc4ca5SDavid du Colombier 		lputl(o1);
136059cc4ca5SDavid du Colombier 		lputl(o2);
136159cc4ca5SDavid du Colombier 		lputl(o3);
136259cc4ca5SDavid du Colombier 		lputl(o4);
136359cc4ca5SDavid du Colombier 		lputl(o5);
136459cc4ca5SDavid du Colombier 		lputl(o6);
136559cc4ca5SDavid du Colombier 		break;
13667dd7cddfSDavid du Colombier 	}
13677dd7cddfSDavid du Colombier }
13687dd7cddfSDavid du Colombier 
13697dd7cddfSDavid du Colombier long
13707dd7cddfSDavid du Colombier oprrr(int a, int sc)
13717dd7cddfSDavid du Colombier {
13727dd7cddfSDavid du Colombier 	long o;
13737dd7cddfSDavid du Colombier 
13747dd7cddfSDavid du Colombier 	o = (sc & C_SCOND) << 28;
13757dd7cddfSDavid du Colombier 	if(sc & C_SBIT)
13767dd7cddfSDavid du Colombier 		o |= 1 << 20;
13777dd7cddfSDavid du Colombier 	if(sc & (C_PBIT|C_WBIT))
13787dd7cddfSDavid du Colombier 		diag(".P/.W on dp instruction");
13797dd7cddfSDavid du Colombier 	switch(a) {
13807dd7cddfSDavid du Colombier 	case AMULU:
13817dd7cddfSDavid du Colombier 	case AMUL:	return o | (0x0<<21) | (0x9<<4);
138259cc4ca5SDavid du Colombier 	case AMULA:	return o | (0x1<<21) | (0x9<<4);
138359cc4ca5SDavid du Colombier 	case AMULLU:	return o | (0x4<<21) | (0x9<<4);
138459cc4ca5SDavid du Colombier 	case AMULL:	return o | (0x6<<21) | (0x9<<4);
138559cc4ca5SDavid du Colombier 	case AMULALU:	return o | (0x5<<21) | (0x9<<4);
138659cc4ca5SDavid du Colombier 	case AMULAL:	return o | (0x7<<21) | (0x9<<4);
13877dd7cddfSDavid du Colombier 	case AAND:	return o | (0x0<<21);
13887dd7cddfSDavid du Colombier 	case AEOR:	return o | (0x1<<21);
13897dd7cddfSDavid du Colombier 	case ASUB:	return o | (0x2<<21);
13907dd7cddfSDavid du Colombier 	case ARSB:	return o | (0x3<<21);
13917dd7cddfSDavid du Colombier 	case AADD:	return o | (0x4<<21);
13927dd7cddfSDavid du Colombier 	case AADC:	return o | (0x5<<21);
13937dd7cddfSDavid du Colombier 	case ASBC:	return o | (0x6<<21);
13947dd7cddfSDavid du Colombier 	case ARSC:	return o | (0x7<<21);
13957dd7cddfSDavid du Colombier 	case ATST:	return o | (0x8<<21) | (1<<20);
13967dd7cddfSDavid du Colombier 	case ATEQ:	return o | (0x9<<21) | (1<<20);
13977dd7cddfSDavid du Colombier 	case ACMP:	return o | (0xa<<21) | (1<<20);
139859cc4ca5SDavid du Colombier 	case ACMN:	return o | (0xb<<21) | (1<<20);
13997dd7cddfSDavid du Colombier 	case AORR:	return o | (0xc<<21);
14007dd7cddfSDavid du Colombier 	case AMOVW:	return o | (0xd<<21);
14017dd7cddfSDavid du Colombier 	case ABIC:	return o | (0xe<<21);
14027dd7cddfSDavid du Colombier 	case AMVN:	return o | (0xf<<21);
14037dd7cddfSDavid du Colombier 	case ASLL:	return o | (0xd<<21) | (0<<5);
14047dd7cddfSDavid du Colombier 	case ASRL:	return o | (0xd<<21) | (1<<5);
14057dd7cddfSDavid du Colombier 	case ASRA:	return o | (0xd<<21) | (2<<5);
14067dd7cddfSDavid du Colombier 	case ASWI:	return o | (0xf<<24);
14077dd7cddfSDavid du Colombier 
14087dd7cddfSDavid du Colombier 	case AADDD:	return o | (0xe<<24) | (0x0<<20) | (1<<8) | (1<<7);
14097dd7cddfSDavid du Colombier 	case AADDF:	return o | (0xe<<24) | (0x0<<20) | (1<<8);
14107dd7cddfSDavid du Colombier 	case AMULD:	return o | (0xe<<24) | (0x1<<20) | (1<<8) | (1<<7);
14117dd7cddfSDavid du Colombier 	case AMULF:	return o | (0xe<<24) | (0x1<<20) | (1<<8);
14127dd7cddfSDavid du Colombier 	case ASUBD:	return o | (0xe<<24) | (0x2<<20) | (1<<8) | (1<<7);
14137dd7cddfSDavid du Colombier 	case ASUBF:	return o | (0xe<<24) | (0x2<<20) | (1<<8);
14147dd7cddfSDavid du Colombier 	case ADIVD:	return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7);
14157dd7cddfSDavid du Colombier 	case ADIVF:	return o | (0xe<<24) | (0x4<<20) | (1<<8);
14167dd7cddfSDavid du Colombier 	case ACMPD:
14177dd7cddfSDavid du Colombier 	case ACMPF:	return o | (0xe<<24) | (0x9<<20) | (0xF<<12) | (1<<8) | (1<<4);	/* arguably, ACMPF should expand to RNDF, CMPD */
14187dd7cddfSDavid du Colombier 
14197dd7cddfSDavid du Colombier 	case AMOVF:
14207dd7cddfSDavid du Colombier 	case AMOVDF:	return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8);
14217dd7cddfSDavid du Colombier 	case AMOVD:
14227dd7cddfSDavid du Colombier 	case AMOVFD:	return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7);
14237dd7cddfSDavid du Colombier 
14247dd7cddfSDavid du Colombier 	case AMOVWF:	return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4);
14257dd7cddfSDavid du Colombier 	case AMOVWD:	return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4) | (1<<7);
14267dd7cddfSDavid du Colombier 	case AMOVFW:	return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4);
14277dd7cddfSDavid du Colombier 	case AMOVDW:	return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4) | (1<<7);
14287dd7cddfSDavid du Colombier 	}
14297dd7cddfSDavid du Colombier 	diag("bad rrr %d", a);
14307dd7cddfSDavid du Colombier 	prasm(curp);
14317dd7cddfSDavid du Colombier 	return 0;
14327dd7cddfSDavid du Colombier }
14337dd7cddfSDavid du Colombier 
14347dd7cddfSDavid du Colombier long
14357dd7cddfSDavid du Colombier opbra(int a, int sc)
14367dd7cddfSDavid du Colombier {
14377dd7cddfSDavid du Colombier 
14387dd7cddfSDavid du Colombier 	if(sc & (C_SBIT|C_PBIT|C_WBIT))
14397dd7cddfSDavid du Colombier 		diag(".S/.P/.W on bra instruction");
14407dd7cddfSDavid du Colombier 	sc &= C_SCOND;
14417dd7cddfSDavid du Colombier 	if(a == ABL)
14427dd7cddfSDavid du Colombier 		return (sc<<28)|(0x5<<25)|(0x1<<24);
14437dd7cddfSDavid du Colombier 	if(sc != 0xe)
14447dd7cddfSDavid du Colombier 		diag(".COND on bcond instruction");
14457dd7cddfSDavid du Colombier 	switch(a) {
14467dd7cddfSDavid du Colombier 	case ABEQ:	return (0x0<<28)|(0x5<<25);
14477dd7cddfSDavid du Colombier 	case ABNE:	return (0x1<<28)|(0x5<<25);
14487dd7cddfSDavid du Colombier 	case ABCS:	return (0x2<<28)|(0x5<<25);
14497dd7cddfSDavid du Colombier 	case ABHS:	return (0x2<<28)|(0x5<<25);
14507dd7cddfSDavid du Colombier 	case ABCC:	return (0x3<<28)|(0x5<<25);
14517dd7cddfSDavid du Colombier 	case ABLO:	return (0x3<<28)|(0x5<<25);
14527dd7cddfSDavid du Colombier 	case ABMI:	return (0x4<<28)|(0x5<<25);
14537dd7cddfSDavid du Colombier 	case ABPL:	return (0x5<<28)|(0x5<<25);
14547dd7cddfSDavid du Colombier 	case ABVS:	return (0x6<<28)|(0x5<<25);
14557dd7cddfSDavid du Colombier 	case ABVC:	return (0x7<<28)|(0x5<<25);
14567dd7cddfSDavid du Colombier 	case ABHI:	return (0x8<<28)|(0x5<<25);
14577dd7cddfSDavid du Colombier 	case ABLS:	return (0x9<<28)|(0x5<<25);
14587dd7cddfSDavid du Colombier 	case ABGE:	return (0xa<<28)|(0x5<<25);
14597dd7cddfSDavid du Colombier 	case ABLT:	return (0xb<<28)|(0x5<<25);
14607dd7cddfSDavid du Colombier 	case ABGT:	return (0xc<<28)|(0x5<<25);
14617dd7cddfSDavid du Colombier 	case ABLE:	return (0xd<<28)|(0x5<<25);
14627dd7cddfSDavid du Colombier 	case AB:	return (0xe<<28)|(0x5<<25);
14637dd7cddfSDavid du Colombier 	}
14647dd7cddfSDavid du Colombier 	diag("bad bra %A", a);
14657dd7cddfSDavid du Colombier 	prasm(curp);
14667dd7cddfSDavid du Colombier 	return 0;
14677dd7cddfSDavid du Colombier }
14687dd7cddfSDavid du Colombier 
14697dd7cddfSDavid du Colombier long
14707dd7cddfSDavid du Colombier olr(long v, int b, int r, int sc)
14717dd7cddfSDavid du Colombier {
14727dd7cddfSDavid du Colombier 	long o;
14737dd7cddfSDavid du Colombier 
14747dd7cddfSDavid du Colombier 	if(sc & C_SBIT)
14757dd7cddfSDavid du Colombier 		diag(".S on LDR/STR instruction");
14767dd7cddfSDavid du Colombier 	o = (sc & C_SCOND) << 28;
14777dd7cddfSDavid du Colombier 	if(!(sc & C_PBIT))
14787dd7cddfSDavid du Colombier 		o |= 1 << 24;
147959cc4ca5SDavid du Colombier 	if(!(sc & C_UBIT))
148059cc4ca5SDavid du Colombier 		o |= 1 << 23;
14817dd7cddfSDavid du Colombier 	if(sc & C_WBIT)
14827dd7cddfSDavid du Colombier 		o |= 1 << 21;
148359cc4ca5SDavid du Colombier 	o |= (0x1<<26) | (1<<20);
14847dd7cddfSDavid du Colombier 	if(v < 0) {
14857dd7cddfSDavid du Colombier 		v = -v;
14867dd7cddfSDavid du Colombier 		o ^= 1 << 23;
14877dd7cddfSDavid du Colombier 	}
14887dd7cddfSDavid du Colombier 	if(v >= (1<<12))
1489406758d9SDavid du Colombier 		diag("literal span too large: %ld (R%d)\n%P", v, b, PP);
14907dd7cddfSDavid du Colombier 	o |= v;
14917dd7cddfSDavid du Colombier 	o |= b << 16;
14927dd7cddfSDavid du Colombier 	o |= r << 12;
14937dd7cddfSDavid du Colombier 	return o;
14947dd7cddfSDavid du Colombier }
14957dd7cddfSDavid du Colombier 
14967dd7cddfSDavid du Colombier long
149759cc4ca5SDavid du Colombier olhr(long v, int b, int r, int sc)
149859cc4ca5SDavid du Colombier {
149959cc4ca5SDavid du Colombier 	long o;
150059cc4ca5SDavid du Colombier 
150159cc4ca5SDavid du Colombier 	if(sc & C_SBIT)
150259cc4ca5SDavid du Colombier 		diag(".S on LDRH/STRH instruction");
150359cc4ca5SDavid du Colombier 	o = (sc & C_SCOND) << 28;
150459cc4ca5SDavid du Colombier 	if(!(sc & C_PBIT))
150559cc4ca5SDavid du Colombier 		o |= 1 << 24;
150659cc4ca5SDavid du Colombier 	if(sc & C_WBIT)
150759cc4ca5SDavid du Colombier 		o |= 1 << 21;
150859cc4ca5SDavid du Colombier 	o |= (1<<23) | (1<<20)|(0xb<<4);
150959cc4ca5SDavid du Colombier 	if(v < 0) {
151059cc4ca5SDavid du Colombier 		v = -v;
151159cc4ca5SDavid du Colombier 		o ^= 1 << 23;
151259cc4ca5SDavid du Colombier 	}
151359cc4ca5SDavid du Colombier 	if(v >= (1<<8))
1514406758d9SDavid du Colombier 		diag("literal span too large: %ld (R%d)\n%P", v, b, PP);
151559cc4ca5SDavid du Colombier 	o |= (v&0xf)|((v>>4)<<8)|(1<<22);
151659cc4ca5SDavid du Colombier 	o |= b << 16;
151759cc4ca5SDavid du Colombier 	o |= r << 12;
151859cc4ca5SDavid du Colombier 	return o;
151959cc4ca5SDavid du Colombier }
152059cc4ca5SDavid du Colombier 
152159cc4ca5SDavid du Colombier long
15227dd7cddfSDavid du Colombier osr(int a, int r, long v, int b, int sc)
15237dd7cddfSDavid du Colombier {
15247dd7cddfSDavid du Colombier 	long o;
15257dd7cddfSDavid du Colombier 
15267dd7cddfSDavid du Colombier 	o = olr(v, b, r, sc) ^ (1<<20);
15277dd7cddfSDavid du Colombier 	if(a != AMOVW)
15287dd7cddfSDavid du Colombier 		o |= 1<<22;
15297dd7cddfSDavid du Colombier 	return o;
15307dd7cddfSDavid du Colombier }
15317dd7cddfSDavid du Colombier 
15327dd7cddfSDavid du Colombier long
153359cc4ca5SDavid du Colombier oshr(int r, long v, int b, int sc)
153459cc4ca5SDavid du Colombier {
153559cc4ca5SDavid du Colombier 	long o;
153659cc4ca5SDavid du Colombier 
153759cc4ca5SDavid du Colombier 	o = olhr(v, b, r, sc) ^ (1<<20);
153859cc4ca5SDavid du Colombier 	return o;
153959cc4ca5SDavid du Colombier }
154059cc4ca5SDavid du Colombier 
154159cc4ca5SDavid du Colombier 
154259cc4ca5SDavid du Colombier long
15437dd7cddfSDavid du Colombier osrr(int r, int i, int b, int sc)
15447dd7cddfSDavid du Colombier {
15457dd7cddfSDavid du Colombier 
15467dd7cddfSDavid du Colombier 	return olr(i, b, r, sc) ^ ((1<<25) | (1<<20));
15477dd7cddfSDavid du Colombier }
15487dd7cddfSDavid du Colombier 
15497dd7cddfSDavid du Colombier long
15507dd7cddfSDavid du Colombier oshrr(int r, int i, int b, int sc)
15517dd7cddfSDavid du Colombier {
155259cc4ca5SDavid du Colombier 	return olhr(i, b, r, sc) ^ ((1<<22) | (1<<20));
15537dd7cddfSDavid du Colombier }
15547dd7cddfSDavid du Colombier 
15557dd7cddfSDavid du Colombier long
15567dd7cddfSDavid du Colombier olrr(int i, int b, int r, int sc)
15577dd7cddfSDavid du Colombier {
15587dd7cddfSDavid du Colombier 
15597dd7cddfSDavid du Colombier 	return olr(i, b, r, sc) ^ (1<<25);
15607dd7cddfSDavid du Colombier }
15617dd7cddfSDavid du Colombier 
15627dd7cddfSDavid du Colombier long
156359cc4ca5SDavid du Colombier olhrr(int i, int b, int r, int sc)
156459cc4ca5SDavid du Colombier {
156559cc4ca5SDavid du Colombier 	return olhr(i, b, r, sc) ^ (1<<22);
156659cc4ca5SDavid du Colombier }
156759cc4ca5SDavid du Colombier 
156859cc4ca5SDavid du Colombier long
156959cc4ca5SDavid du Colombier ofsr(int a, int r, long v, int b, int sc, Prog *p)
15707dd7cddfSDavid du Colombier {
15717dd7cddfSDavid du Colombier 	long o;
15727dd7cddfSDavid du Colombier 
15737dd7cddfSDavid du Colombier 	if(sc & C_SBIT)
15747dd7cddfSDavid du Colombier 		diag(".S on FLDR/FSTR instruction");
15757dd7cddfSDavid du Colombier 	o = (sc & C_SCOND) << 28;
15767dd7cddfSDavid du Colombier 	if(!(sc & C_PBIT))
15777dd7cddfSDavid du Colombier 		o |= 1 << 24;
15787dd7cddfSDavid du Colombier 	if(sc & C_WBIT)
15797dd7cddfSDavid du Colombier 		o |= 1 << 21;
15807dd7cddfSDavid du Colombier 	o |= (6<<25) | (1<<24) | (1<<23);
15817dd7cddfSDavid du Colombier 	if(v < 0) {
15827dd7cddfSDavid du Colombier 		v = -v;
15837dd7cddfSDavid du Colombier 		o ^= 1 << 23;
15847dd7cddfSDavid du Colombier 	}
15857dd7cddfSDavid du Colombier 	if(v & 3)
1586406758d9SDavid du Colombier 		diag("odd offset for floating point op: %ld\n%P", v, p);
15877dd7cddfSDavid du Colombier 	else if(v >= (1<<10))
1588406758d9SDavid du Colombier 		diag("literal span too large: %ld\n%P", v, p);
15897dd7cddfSDavid du Colombier 	o |= (v>>2) & 0xFF;
15907dd7cddfSDavid du Colombier 	o |= b << 16;
15917dd7cddfSDavid du Colombier 	o |= r << 12;
15927dd7cddfSDavid du Colombier 	o |= 1 << 8;
15937dd7cddfSDavid du Colombier 
15947dd7cddfSDavid du Colombier 	switch(a) {
15957dd7cddfSDavid du Colombier 	default:
15967dd7cddfSDavid du Colombier 		diag("bad fst %A", a);
15977dd7cddfSDavid du Colombier 	case AMOVD:
15987dd7cddfSDavid du Colombier 		o |= 1<<15;
15997dd7cddfSDavid du Colombier 	case AMOVF:
16007dd7cddfSDavid du Colombier 		break;
16017dd7cddfSDavid du Colombier 	}
16027dd7cddfSDavid du Colombier 	return o;
16037dd7cddfSDavid du Colombier }
16047dd7cddfSDavid du Colombier 
160559cc4ca5SDavid du Colombier long
160659cc4ca5SDavid du Colombier omvl(Prog *p, Adr *a, int dr)
160759cc4ca5SDavid du Colombier {
160859cc4ca5SDavid du Colombier 	long v, o1;
160959cc4ca5SDavid du Colombier 	if(!p->cond) {
161059cc4ca5SDavid du Colombier 		aclass(a);
161159cc4ca5SDavid du Colombier 		v = immrot(~instoffset);
161259cc4ca5SDavid du Colombier 		if(v == 0) {
161359cc4ca5SDavid du Colombier 			diag("missing literal");
161459cc4ca5SDavid du Colombier 			prasm(p);
161559cc4ca5SDavid du Colombier 			return 0;
161659cc4ca5SDavid du Colombier 		}
161759cc4ca5SDavid du Colombier 		o1 = oprrr(AMVN, p->scond&C_SCOND);
161859cc4ca5SDavid du Colombier 		o1 |= v;
161959cc4ca5SDavid du Colombier 		o1 |= dr << 12;
162059cc4ca5SDavid du Colombier 	} else {
162159cc4ca5SDavid du Colombier 		v = p->cond->pc - p->pc - 8;
162259cc4ca5SDavid du Colombier 		o1 = olr(v, REGPC, dr, p->scond&C_SCOND);
162359cc4ca5SDavid du Colombier 	}
162459cc4ca5SDavid du Colombier 	return o1;
162559cc4ca5SDavid du Colombier }
162659cc4ca5SDavid du Colombier 
16277dd7cddfSDavid du Colombier static Ieee chipfloats[] = {
16287dd7cddfSDavid du Colombier 	{0x00000000, 0x00000000}, /* 0 */
16297dd7cddfSDavid du Colombier 	{0x00000000, 0x3ff00000}, /* 1 */
16307dd7cddfSDavid du Colombier 	{0x00000000, 0x40000000}, /* 2 */
16317dd7cddfSDavid du Colombier 	{0x00000000, 0x40080000}, /* 3 */
16327dd7cddfSDavid du Colombier 	{0x00000000, 0x40100000}, /* 4 */
16337dd7cddfSDavid du Colombier 	{0x00000000, 0x40140000}, /* 5 */
16347dd7cddfSDavid du Colombier 	{0x00000000, 0x3fe00000}, /* .5 */
16357dd7cddfSDavid du Colombier 	{0x00000000, 0x40240000}, /* 10 */
16367dd7cddfSDavid du Colombier };
16377dd7cddfSDavid du Colombier 
16387dd7cddfSDavid du Colombier int
16397dd7cddfSDavid du Colombier chipfloat(Ieee *e)
16407dd7cddfSDavid du Colombier {
16417dd7cddfSDavid du Colombier 	Ieee *p;
16427dd7cddfSDavid du Colombier 	int n;
16437dd7cddfSDavid du Colombier 
16447dd7cddfSDavid du Colombier 	for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){
16457dd7cddfSDavid du Colombier 		p = &chipfloats[n];
16467dd7cddfSDavid du Colombier 		if(p->l == e->l && p->h == e->h)
16477dd7cddfSDavid du Colombier 			return n;
16487dd7cddfSDavid du Colombier 	}
16497dd7cddfSDavid du Colombier 	return -1;
16507dd7cddfSDavid du Colombier }
1651