xref: /plan9-contrib/sys/src/cmd/il/asm.c (revision ce95e1b3727b9cb1c223ffbed69aff21a8ced255)
1*ce95e1b3SDavid du Colombier #include	"l.h"
2*ce95e1b3SDavid du Colombier 
3*ce95e1b3SDavid du Colombier long	OFFSET;
4*ce95e1b3SDavid du Colombier 
5*ce95e1b3SDavid du Colombier xlong
entryvalue(void)6*ce95e1b3SDavid du Colombier entryvalue(void)
7*ce95e1b3SDavid du Colombier {
8*ce95e1b3SDavid du Colombier 	char *a;
9*ce95e1b3SDavid du Colombier 	Sym *s;
10*ce95e1b3SDavid du Colombier 
11*ce95e1b3SDavid du Colombier 	a = INITENTRY;
12*ce95e1b3SDavid du Colombier 	if(*a >= '0' && *a <= '9')
13*ce95e1b3SDavid du Colombier 		return atolwhex(a);
14*ce95e1b3SDavid du Colombier 	s = lookup(a, 0);
15*ce95e1b3SDavid du Colombier 	if(s->type == 0)
16*ce95e1b3SDavid du Colombier 		return INITTEXT;
17*ce95e1b3SDavid du Colombier 	if(s->type != STEXT && s->type != SLEAF)
18*ce95e1b3SDavid du Colombier 		diag("entry not text: %s", s->name);
19*ce95e1b3SDavid du Colombier 	return s->value + INITTEXT;
20*ce95e1b3SDavid du Colombier }
21*ce95e1b3SDavid du Colombier 
22*ce95e1b3SDavid du Colombier void
asmb(void)23*ce95e1b3SDavid du Colombier asmb(void)
24*ce95e1b3SDavid du Colombier {
25*ce95e1b3SDavid du Colombier 	Prog *p;
26*ce95e1b3SDavid du Colombier 	long t, etext;
27*ce95e1b3SDavid du Colombier 	Optab *o;
28*ce95e1b3SDavid du Colombier 
29*ce95e1b3SDavid du Colombier 	if(debug['v'])
30*ce95e1b3SDavid du Colombier 		Bprint(&bso, "%5.2f asm\n", cputime());
31*ce95e1b3SDavid du Colombier 	Bflush(&bso);
32*ce95e1b3SDavid du Colombier 	OFFSET = HEADR;
33*ce95e1b3SDavid du Colombier 	seek(cout, OFFSET, 0);
34*ce95e1b3SDavid du Colombier 	pc = 0;
35*ce95e1b3SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
36*ce95e1b3SDavid du Colombier 		if(p->as == ATEXT) {
37*ce95e1b3SDavid du Colombier 			/* align on word boundary */
38*ce95e1b3SDavid du Colombier 			if(!debug['c'] && (pc & 2) != 0){
39*ce95e1b3SDavid du Colombier 				nopalign.pc = pc;
40*ce95e1b3SDavid du Colombier 				pc += asmout(&nopalign, oplook(&nopalign), 0);
41*ce95e1b3SDavid du Colombier 			}
42*ce95e1b3SDavid du Colombier 			curtext = p;
43*ce95e1b3SDavid du Colombier 			autosize = p->to.offset + ptrsize;
44*ce95e1b3SDavid du Colombier 		}
45*ce95e1b3SDavid du Colombier 		if(p->pc != pc) {
46*ce95e1b3SDavid du Colombier 			diag("phase error %lux sb %lux",
47*ce95e1b3SDavid du Colombier 				p->pc, pc);
48*ce95e1b3SDavid du Colombier 			if(!debug['a'])
49*ce95e1b3SDavid du Colombier 				prasm(curp);
50*ce95e1b3SDavid du Colombier 			pc = p->pc;
51*ce95e1b3SDavid du Colombier 		}
52*ce95e1b3SDavid du Colombier 		curp = p;
53*ce95e1b3SDavid du Colombier 		o = oplook(p);	/* could probably avoid this call */
54*ce95e1b3SDavid du Colombier 		pc += asmout(p, o, 0);
55*ce95e1b3SDavid du Colombier 	}
56*ce95e1b3SDavid du Colombier 	if(debug['a'])
57*ce95e1b3SDavid du Colombier 		Bprint(&bso, "\n");
58*ce95e1b3SDavid du Colombier 	Bflush(&bso);
59*ce95e1b3SDavid du Colombier 	cflush();
60*ce95e1b3SDavid du Colombier 
61*ce95e1b3SDavid du Colombier 	etext = textsize;
62*ce95e1b3SDavid du Colombier 	for(t = pc; t < etext; t += sizeof(buf)-100) {
63*ce95e1b3SDavid du Colombier 		if(etext-t > sizeof(buf)-100)
64*ce95e1b3SDavid du Colombier 			datblk(t, sizeof(buf)-100, 1);
65*ce95e1b3SDavid du Colombier 		else
66*ce95e1b3SDavid du Colombier 			datblk(t, etext-t, 1);
67*ce95e1b3SDavid du Colombier 	}
68*ce95e1b3SDavid du Colombier 
69*ce95e1b3SDavid du Colombier 	Bflush(&bso);
70*ce95e1b3SDavid du Colombier 	cflush();
71*ce95e1b3SDavid du Colombier 
72*ce95e1b3SDavid du Colombier 	curtext = P;
73*ce95e1b3SDavid du Colombier 	switch(HEADTYPE) {
74*ce95e1b3SDavid du Colombier 	case 0:
75*ce95e1b3SDavid du Colombier 	case 4:
76*ce95e1b3SDavid du Colombier 		OFFSET = rnd(HEADR+textsize, 4096);
77*ce95e1b3SDavid du Colombier 		seek(cout, OFFSET, 0);
78*ce95e1b3SDavid du Colombier 		break;
79*ce95e1b3SDavid du Colombier 	case 1:
80*ce95e1b3SDavid du Colombier 	case 2:
81*ce95e1b3SDavid du Colombier 	case 3:
82*ce95e1b3SDavid du Colombier 	case 5:
83*ce95e1b3SDavid du Colombier 	case 6:
84*ce95e1b3SDavid du Colombier 		OFFSET = HEADR+textsize;
85*ce95e1b3SDavid du Colombier 		seek(cout, OFFSET, 0);
86*ce95e1b3SDavid du Colombier 		break;
87*ce95e1b3SDavid du Colombier 	}
88*ce95e1b3SDavid du Colombier 	for(t = 0; t < datsize; t += sizeof(buf)-100) {
89*ce95e1b3SDavid du Colombier 		if(datsize-t > sizeof(buf)-100)
90*ce95e1b3SDavid du Colombier 			datblk(t, sizeof(buf)-100, 0);
91*ce95e1b3SDavid du Colombier 		else
92*ce95e1b3SDavid du Colombier 			datblk(t, datsize-t, 0);
93*ce95e1b3SDavid du Colombier 	}
94*ce95e1b3SDavid du Colombier 
95*ce95e1b3SDavid du Colombier 	symsize = 0;
96*ce95e1b3SDavid du Colombier 	lcsize = 0;
97*ce95e1b3SDavid du Colombier 	if(!debug['s']) {
98*ce95e1b3SDavid du Colombier 		if(debug['v'])
99*ce95e1b3SDavid du Colombier 			Bprint(&bso, "%5.2f sym\n", cputime());
100*ce95e1b3SDavid du Colombier 		Bflush(&bso);
101*ce95e1b3SDavid du Colombier 		switch(HEADTYPE) {
102*ce95e1b3SDavid du Colombier 		case 0:
103*ce95e1b3SDavid du Colombier 		case 4:
104*ce95e1b3SDavid du Colombier 			OFFSET = rnd(HEADR+textsize, 4096)+datsize;
105*ce95e1b3SDavid du Colombier 			seek(cout, OFFSET, 0);
106*ce95e1b3SDavid du Colombier 			break;
107*ce95e1b3SDavid du Colombier 		case 3:
108*ce95e1b3SDavid du Colombier 		case 2:
109*ce95e1b3SDavid du Colombier 		case 1:
110*ce95e1b3SDavid du Colombier 		case 5:
111*ce95e1b3SDavid du Colombier 		case 6:
112*ce95e1b3SDavid du Colombier 			OFFSET = HEADR+textsize+datsize;
113*ce95e1b3SDavid du Colombier 			seek(cout, OFFSET, 0);
114*ce95e1b3SDavid du Colombier 			break;
115*ce95e1b3SDavid du Colombier 		}
116*ce95e1b3SDavid du Colombier 		if(!debug['s'])
117*ce95e1b3SDavid du Colombier 			asmsym();
118*ce95e1b3SDavid du Colombier 		if(debug['v'])
119*ce95e1b3SDavid du Colombier 			Bprint(&bso, "%5.2f pc\n", cputime());
120*ce95e1b3SDavid du Colombier 		Bflush(&bso);
121*ce95e1b3SDavid du Colombier 		if(!debug['s'])
122*ce95e1b3SDavid du Colombier 			asmlc();
123*ce95e1b3SDavid du Colombier 		cflush();
124*ce95e1b3SDavid du Colombier 	}
125*ce95e1b3SDavid du Colombier 
126*ce95e1b3SDavid du Colombier 	if(debug['v'])
127*ce95e1b3SDavid du Colombier 		Bprint(&bso, "%5.2f header\n", cputime());
128*ce95e1b3SDavid du Colombier 	Bflush(&bso);
129*ce95e1b3SDavid du Colombier 	OFFSET = 0;
130*ce95e1b3SDavid du Colombier 	seek(cout, OFFSET, 0);
131*ce95e1b3SDavid du Colombier 	switch(HEADTYPE) {
132*ce95e1b3SDavid du Colombier 	case 1:
133*ce95e1b3SDavid du Colombier 		break;
134*ce95e1b3SDavid du Colombier 	case 2:
135*ce95e1b3SDavid du Colombier 		/* XXX expanded header needed? */
136*ce95e1b3SDavid du Colombier 		t = thechar == 'j' ? 30 : 29;
137*ce95e1b3SDavid du Colombier 		lput(((((4*t)+0)*t)+7));	/* magic */
138*ce95e1b3SDavid du Colombier 		lput(textsize);			/* sizes */
139*ce95e1b3SDavid du Colombier 		lput(datsize);
140*ce95e1b3SDavid du Colombier 		lput(bsssize);
141*ce95e1b3SDavid du Colombier 		lput(symsize);			/* nsyms */
142*ce95e1b3SDavid du Colombier 		lput(entryvalue());		/* va of entry */
143*ce95e1b3SDavid du Colombier 		lput(0L);
144*ce95e1b3SDavid du Colombier 		lput(lcsize);
145*ce95e1b3SDavid du Colombier 		break;
146*ce95e1b3SDavid du Colombier 	case 5:
147*ce95e1b3SDavid du Colombier 		if(thechar == 'j')
148*ce95e1b3SDavid du Colombier 			elf64(243, ELFDATA2LSB, 0, nil);		/* 243 is RISCV */
149*ce95e1b3SDavid du Colombier 		else
150*ce95e1b3SDavid du Colombier 			elf32(243, ELFDATA2LSB, 0, nil);
151*ce95e1b3SDavid du Colombier 	}
152*ce95e1b3SDavid du Colombier 	cflush();
153*ce95e1b3SDavid du Colombier }
154*ce95e1b3SDavid du Colombier 
155*ce95e1b3SDavid du Colombier void
strnput(char * s,int n)156*ce95e1b3SDavid du Colombier strnput(char *s, int n)
157*ce95e1b3SDavid du Colombier {
158*ce95e1b3SDavid du Colombier 	for(; *s; s++){
159*ce95e1b3SDavid du Colombier 		cput(*s);
160*ce95e1b3SDavid du Colombier 		n--;
161*ce95e1b3SDavid du Colombier 	}
162*ce95e1b3SDavid du Colombier 	for(; n > 0; n--)
163*ce95e1b3SDavid du Colombier 		cput(0);
164*ce95e1b3SDavid du Colombier }
165*ce95e1b3SDavid du Colombier 
166*ce95e1b3SDavid du Colombier void
cput(int c)167*ce95e1b3SDavid du Colombier cput(int c)
168*ce95e1b3SDavid du Colombier {
169*ce95e1b3SDavid du Colombier 	cbp[0] = c;
170*ce95e1b3SDavid du Colombier 	cbp++;
171*ce95e1b3SDavid du Colombier 	cbc--;
172*ce95e1b3SDavid du Colombier 	if(cbc <= 0)
173*ce95e1b3SDavid du Colombier 		cflush();
174*ce95e1b3SDavid du Colombier }
175*ce95e1b3SDavid du Colombier 
176*ce95e1b3SDavid du Colombier void
wput(long l)177*ce95e1b3SDavid du Colombier wput(long l)
178*ce95e1b3SDavid du Colombier {
179*ce95e1b3SDavid du Colombier 
180*ce95e1b3SDavid du Colombier 	cbp[0] = l>>8;
181*ce95e1b3SDavid du Colombier 	cbp[1] = l;
182*ce95e1b3SDavid du Colombier 	cbp += 2;
183*ce95e1b3SDavid du Colombier 	cbc -= 2;
184*ce95e1b3SDavid du Colombier 	if(cbc <= 0)
185*ce95e1b3SDavid du Colombier 		cflush();
186*ce95e1b3SDavid du Colombier }
187*ce95e1b3SDavid du Colombier 
188*ce95e1b3SDavid du Colombier void
wputl(long l)189*ce95e1b3SDavid du Colombier wputl(long l)
190*ce95e1b3SDavid du Colombier {
191*ce95e1b3SDavid du Colombier 
192*ce95e1b3SDavid du Colombier 	cbp[0] = l;
193*ce95e1b3SDavid du Colombier 	cbp[1] = l>>8;
194*ce95e1b3SDavid du Colombier 	cbp += 2;
195*ce95e1b3SDavid du Colombier 	cbc -= 2;
196*ce95e1b3SDavid du Colombier 	if(cbc <= 0)
197*ce95e1b3SDavid du Colombier 		cflush();
198*ce95e1b3SDavid du Colombier }
199*ce95e1b3SDavid du Colombier 
200*ce95e1b3SDavid du Colombier void
lput(long l)201*ce95e1b3SDavid du Colombier lput(long l)
202*ce95e1b3SDavid du Colombier {
203*ce95e1b3SDavid du Colombier 
204*ce95e1b3SDavid du Colombier 	cbp[0] = l>>24;
205*ce95e1b3SDavid du Colombier 	cbp[1] = l>>16;
206*ce95e1b3SDavid du Colombier 	cbp[2] = l>>8;
207*ce95e1b3SDavid du Colombier 	cbp[3] = l;
208*ce95e1b3SDavid du Colombier 	cbp += 4;
209*ce95e1b3SDavid du Colombier 	cbc -= 4;
210*ce95e1b3SDavid du Colombier 	if(cbc <= 0)
211*ce95e1b3SDavid du Colombier 		cflush();
212*ce95e1b3SDavid du Colombier }
213*ce95e1b3SDavid du Colombier 
214*ce95e1b3SDavid du Colombier void
lputl(long l)215*ce95e1b3SDavid du Colombier lputl(long l)
216*ce95e1b3SDavid du Colombier {
217*ce95e1b3SDavid du Colombier 
218*ce95e1b3SDavid du Colombier 	cbp[3] = l>>24;
219*ce95e1b3SDavid du Colombier 	cbp[2] = l>>16;
220*ce95e1b3SDavid du Colombier 	cbp[1] = l>>8;
221*ce95e1b3SDavid du Colombier 	cbp[0] = l;
222*ce95e1b3SDavid du Colombier 	cbp += 4;
223*ce95e1b3SDavid du Colombier 	cbc -= 4;
224*ce95e1b3SDavid du Colombier 	if(cbc <= 0)
225*ce95e1b3SDavid du Colombier 		cflush();
226*ce95e1b3SDavid du Colombier }
227*ce95e1b3SDavid du Colombier 
228*ce95e1b3SDavid du Colombier void
llput(vlong v)229*ce95e1b3SDavid du Colombier llput(vlong v)
230*ce95e1b3SDavid du Colombier {
231*ce95e1b3SDavid du Colombier 	lput(v>>32);
232*ce95e1b3SDavid du Colombier 	lput(v);
233*ce95e1b3SDavid du Colombier }
234*ce95e1b3SDavid du Colombier 
235*ce95e1b3SDavid du Colombier void
llputl(vlong v)236*ce95e1b3SDavid du Colombier llputl(vlong v)
237*ce95e1b3SDavid du Colombier {
238*ce95e1b3SDavid du Colombier 	lputl(v);
239*ce95e1b3SDavid du Colombier 	lputl(v>>32);
240*ce95e1b3SDavid du Colombier }
241*ce95e1b3SDavid du Colombier 
242*ce95e1b3SDavid du Colombier void
cflush(void)243*ce95e1b3SDavid du Colombier cflush(void)
244*ce95e1b3SDavid du Colombier {
245*ce95e1b3SDavid du Colombier 	int n;
246*ce95e1b3SDavid du Colombier 
247*ce95e1b3SDavid du Colombier 	n = sizeof(buf.cbuf) - cbc;
248*ce95e1b3SDavid du Colombier 	if(n)
249*ce95e1b3SDavid du Colombier 		write(cout, buf.cbuf, n);
250*ce95e1b3SDavid du Colombier 	cbp = buf.cbuf;
251*ce95e1b3SDavid du Colombier 	cbc = sizeof(buf.cbuf);
252*ce95e1b3SDavid du Colombier }
253*ce95e1b3SDavid du Colombier 
254*ce95e1b3SDavid du Colombier void
nopstat(char * f,Count * c)255*ce95e1b3SDavid du Colombier nopstat(char *f, Count *c)
256*ce95e1b3SDavid du Colombier {
257*ce95e1b3SDavid du Colombier 	if(c->outof)
258*ce95e1b3SDavid du Colombier 	Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
259*ce95e1b3SDavid du Colombier 		c->outof - c->count, c->outof,
260*ce95e1b3SDavid du Colombier 		(double)(c->outof - c->count)/c->outof);
261*ce95e1b3SDavid du Colombier }
262*ce95e1b3SDavid du Colombier 
263*ce95e1b3SDavid du Colombier void
asmsym(void)264*ce95e1b3SDavid du Colombier asmsym(void)
265*ce95e1b3SDavid du Colombier {
266*ce95e1b3SDavid du Colombier 	Prog *p;
267*ce95e1b3SDavid du Colombier 	Auto *a;
268*ce95e1b3SDavid du Colombier 	Sym *s;
269*ce95e1b3SDavid du Colombier 	int h;
270*ce95e1b3SDavid du Colombier 
271*ce95e1b3SDavid du Colombier 	s = lookup("etext", 0);
272*ce95e1b3SDavid du Colombier 	if(s->type == STEXT)
273*ce95e1b3SDavid du Colombier 		putsymb(s->name, 'T', s->value+INITTEXT, s->version);
274*ce95e1b3SDavid du Colombier 
275*ce95e1b3SDavid du Colombier 	for(h=0; h<NHASH; h++)
276*ce95e1b3SDavid du Colombier 		for(s=hash[h]; s!=S; s=s->link)
277*ce95e1b3SDavid du Colombier 			switch(s->type) {
278*ce95e1b3SDavid du Colombier 			case SCONST:
279*ce95e1b3SDavid du Colombier 				putsymb(s->name, 'D', s->value, s->version);
280*ce95e1b3SDavid du Colombier 				continue;
281*ce95e1b3SDavid du Colombier 
282*ce95e1b3SDavid du Colombier 			case SSTRING:
283*ce95e1b3SDavid du Colombier 				putsymb(s->name, 'T', s->value, s->version);
284*ce95e1b3SDavid du Colombier 				continue;
285*ce95e1b3SDavid du Colombier 
286*ce95e1b3SDavid du Colombier 			case SDATA:
287*ce95e1b3SDavid du Colombier 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
288*ce95e1b3SDavid du Colombier 				continue;
289*ce95e1b3SDavid du Colombier 
290*ce95e1b3SDavid du Colombier 			case SBSS:
291*ce95e1b3SDavid du Colombier 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
292*ce95e1b3SDavid du Colombier 				continue;
293*ce95e1b3SDavid du Colombier 
294*ce95e1b3SDavid du Colombier 			case SFILE:
295*ce95e1b3SDavid du Colombier 				putsymb(s->name, 'f', s->value, s->version);
296*ce95e1b3SDavid du Colombier 				continue;
297*ce95e1b3SDavid du Colombier 			}
298*ce95e1b3SDavid du Colombier 
299*ce95e1b3SDavid du Colombier 	for(p=textp; p!=P; p=p->cond) {
300*ce95e1b3SDavid du Colombier 		s = p->from.sym;
301*ce95e1b3SDavid du Colombier 		if(s->type != STEXT && s->type != SLEAF)
302*ce95e1b3SDavid du Colombier 			continue;
303*ce95e1b3SDavid du Colombier 
304*ce95e1b3SDavid du Colombier 		/* filenames first */
305*ce95e1b3SDavid du Colombier 		for(a=p->to.autom; a; a=a->link)
306*ce95e1b3SDavid du Colombier 			if(a->type == D_FILE)
307*ce95e1b3SDavid du Colombier 				putsymb(a->asym->name, 'z', a->aoffset, 0);
308*ce95e1b3SDavid du Colombier 			else
309*ce95e1b3SDavid du Colombier 			if(a->type == D_FILE1)
310*ce95e1b3SDavid du Colombier 				putsymb(a->asym->name, 'Z', a->aoffset, 0);
311*ce95e1b3SDavid du Colombier 
312*ce95e1b3SDavid du Colombier 		if(s->type == STEXT)
313*ce95e1b3SDavid du Colombier 			putsymb(s->name, 'T', s->value+INITTEXT, s->version);
314*ce95e1b3SDavid du Colombier 		else
315*ce95e1b3SDavid du Colombier 			putsymb(s->name, 'L', s->value+INITTEXT, s->version);
316*ce95e1b3SDavid du Colombier 
317*ce95e1b3SDavid du Colombier 		/* frame, auto and param after */
318*ce95e1b3SDavid du Colombier 		putsymb(".frame", 'm', p->to.offset+ptrsize, 0);
319*ce95e1b3SDavid du Colombier 		for(a=p->to.autom; a; a=a->link)
320*ce95e1b3SDavid du Colombier 			if(a->type == D_AUTO)
321*ce95e1b3SDavid du Colombier 				putsymb(a->asym->name, 'a', -a->aoffset, 0);
322*ce95e1b3SDavid du Colombier 			else
323*ce95e1b3SDavid du Colombier 			if(a->type == D_PARAM)
324*ce95e1b3SDavid du Colombier 				putsymb(a->asym->name, 'p', a->aoffset, 0);
325*ce95e1b3SDavid du Colombier 	}
326*ce95e1b3SDavid du Colombier 	if(debug['v'] || debug['n'])
327*ce95e1b3SDavid du Colombier 		Bprint(&bso, "symsize = %lud\n", symsize);
328*ce95e1b3SDavid du Colombier 	Bflush(&bso);
329*ce95e1b3SDavid du Colombier }
330*ce95e1b3SDavid du Colombier 
331*ce95e1b3SDavid du Colombier void
putsymb(char * s,int t,vlong v,int ver)332*ce95e1b3SDavid du Colombier putsymb(char *s, int t, vlong v, int ver)
333*ce95e1b3SDavid du Colombier {
334*ce95e1b3SDavid du Colombier 	int i, f, l;
335*ce95e1b3SDavid du Colombier 
336*ce95e1b3SDavid du Colombier 	if(t == 'f')
337*ce95e1b3SDavid du Colombier 		s++;
338*ce95e1b3SDavid du Colombier 	if(thechar == 'j'){
339*ce95e1b3SDavid du Colombier 		l = 8;
340*ce95e1b3SDavid du Colombier 		llput(v);
341*ce95e1b3SDavid du Colombier 	}else{
342*ce95e1b3SDavid du Colombier 		l = 4;
343*ce95e1b3SDavid du Colombier 		lput(v);
344*ce95e1b3SDavid du Colombier 	}
345*ce95e1b3SDavid du Colombier 	if(ver)
346*ce95e1b3SDavid du Colombier 		t += 'a' - 'A';
347*ce95e1b3SDavid du Colombier 	cput(t+0x80);			/* 0x80 is variable length */
348*ce95e1b3SDavid du Colombier 
349*ce95e1b3SDavid du Colombier 	if(t == 'Z' || t == 'z') {
350*ce95e1b3SDavid du Colombier 		cput(s[0]);
351*ce95e1b3SDavid du Colombier 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
352*ce95e1b3SDavid du Colombier 			cput(s[i]);
353*ce95e1b3SDavid du Colombier 			cput(s[i+1]);
354*ce95e1b3SDavid du Colombier 		}
355*ce95e1b3SDavid du Colombier 		cput(0);
356*ce95e1b3SDavid du Colombier 		cput(0);
357*ce95e1b3SDavid du Colombier 		i++;
358*ce95e1b3SDavid du Colombier 	}
359*ce95e1b3SDavid du Colombier 	else {
360*ce95e1b3SDavid du Colombier 		for(i=0; s[i]; i++)
361*ce95e1b3SDavid du Colombier 			cput(s[i]);
362*ce95e1b3SDavid du Colombier 		cput(0);
363*ce95e1b3SDavid du Colombier 	}
364*ce95e1b3SDavid du Colombier 	symsize += l + 1 + i + 1;
365*ce95e1b3SDavid du Colombier 
366*ce95e1b3SDavid du Colombier 	if(debug['n']) {
367*ce95e1b3SDavid du Colombier 		if(t == 'z' || t == 'Z') {
368*ce95e1b3SDavid du Colombier 			Bprint(&bso, "%c %.8llux ", t, v);
369*ce95e1b3SDavid du Colombier 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
370*ce95e1b3SDavid du Colombier 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
371*ce95e1b3SDavid du Colombier 				Bprint(&bso, "/%x", f);
372*ce95e1b3SDavid du Colombier 			}
373*ce95e1b3SDavid du Colombier 			Bprint(&bso, "\n");
374*ce95e1b3SDavid du Colombier 			return;
375*ce95e1b3SDavid du Colombier 		}
376*ce95e1b3SDavid du Colombier 		if(ver)
377*ce95e1b3SDavid du Colombier 			Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
378*ce95e1b3SDavid du Colombier 		else
379*ce95e1b3SDavid du Colombier 			Bprint(&bso, "%c %.8llux %s\n", t, v, s);
380*ce95e1b3SDavid du Colombier 	}
381*ce95e1b3SDavid du Colombier }
382*ce95e1b3SDavid du Colombier 
383*ce95e1b3SDavid du Colombier #define	MINLC	2
384*ce95e1b3SDavid du Colombier void
asmlc(void)385*ce95e1b3SDavid du Colombier asmlc(void)
386*ce95e1b3SDavid du Colombier {
387*ce95e1b3SDavid du Colombier 	long oldpc, oldlc;
388*ce95e1b3SDavid du Colombier 	Prog *p;
389*ce95e1b3SDavid du Colombier 	long v, s;
390*ce95e1b3SDavid du Colombier 
391*ce95e1b3SDavid du Colombier 	oldpc = 0;
392*ce95e1b3SDavid du Colombier 	oldlc = 0;
393*ce95e1b3SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
394*ce95e1b3SDavid du Colombier 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
395*ce95e1b3SDavid du Colombier 			if(p->as == ATEXT)
396*ce95e1b3SDavid du Colombier 				curtext = p;
397*ce95e1b3SDavid du Colombier 			if(debug['L'])
398*ce95e1b3SDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
399*ce95e1b3SDavid du Colombier 					p->pc, p);
400*ce95e1b3SDavid du Colombier 			continue;
401*ce95e1b3SDavid du Colombier 		}
402*ce95e1b3SDavid du Colombier 		if(debug['L'])
403*ce95e1b3SDavid du Colombier 			Bprint(&bso, "\t\t%6ld", lcsize);
404*ce95e1b3SDavid du Colombier 		v = (p->pc - oldpc) / MINLC;
405*ce95e1b3SDavid du Colombier 		while(v) {
406*ce95e1b3SDavid du Colombier 			s = 127;
407*ce95e1b3SDavid du Colombier 			if(v < 127)
408*ce95e1b3SDavid du Colombier 				s = v;
409*ce95e1b3SDavid du Colombier 			cput(s+128);	/* 129-255 +pc */
410*ce95e1b3SDavid du Colombier 			if(debug['L'])
411*ce95e1b3SDavid du Colombier 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
412*ce95e1b3SDavid du Colombier 			v -= s;
413*ce95e1b3SDavid du Colombier 			lcsize++;
414*ce95e1b3SDavid du Colombier 		}
415*ce95e1b3SDavid du Colombier 		s = p->line - oldlc;
416*ce95e1b3SDavid du Colombier 		oldlc = p->line;
417*ce95e1b3SDavid du Colombier 		oldpc = p->pc + MINLC;
418*ce95e1b3SDavid du Colombier 		if(s > 64 || s < -64) {
419*ce95e1b3SDavid du Colombier 			cput(0);	/* 0 vv +lc */
420*ce95e1b3SDavid du Colombier 			cput(s>>24);
421*ce95e1b3SDavid du Colombier 			cput(s>>16);
422*ce95e1b3SDavid du Colombier 			cput(s>>8);
423*ce95e1b3SDavid du Colombier 			cput(s);
424*ce95e1b3SDavid du Colombier 			if(debug['L']) {
425*ce95e1b3SDavid du Colombier 				if(s > 0)
426*ce95e1b3SDavid du Colombier 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
427*ce95e1b3SDavid du Colombier 						s, 0, s);
428*ce95e1b3SDavid du Colombier 				else
429*ce95e1b3SDavid du Colombier 					Bprint(&bso, " lc%ld(%d,%ld)\n",
430*ce95e1b3SDavid du Colombier 						s, 0, s);
431*ce95e1b3SDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
432*ce95e1b3SDavid du Colombier 					p->pc, p);
433*ce95e1b3SDavid du Colombier 			}
434*ce95e1b3SDavid du Colombier 			lcsize += 5;
435*ce95e1b3SDavid du Colombier 			continue;
436*ce95e1b3SDavid du Colombier 		}
437*ce95e1b3SDavid du Colombier 		if(s > 0) {
438*ce95e1b3SDavid du Colombier 			cput(0+s);	/* 1-64 +lc */
439*ce95e1b3SDavid du Colombier 			if(debug['L']) {
440*ce95e1b3SDavid du Colombier 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
441*ce95e1b3SDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
442*ce95e1b3SDavid du Colombier 					p->pc, p);
443*ce95e1b3SDavid du Colombier 			}
444*ce95e1b3SDavid du Colombier 		} else {
445*ce95e1b3SDavid du Colombier 			cput(64-s);	/* 65-128 -lc */
446*ce95e1b3SDavid du Colombier 			if(debug['L']) {
447*ce95e1b3SDavid du Colombier 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
448*ce95e1b3SDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
449*ce95e1b3SDavid du Colombier 					p->pc, p);
450*ce95e1b3SDavid du Colombier 			}
451*ce95e1b3SDavid du Colombier 		}
452*ce95e1b3SDavid du Colombier 		lcsize++;
453*ce95e1b3SDavid du Colombier 	}
454*ce95e1b3SDavid du Colombier 	while(lcsize & 1) {
455*ce95e1b3SDavid du Colombier 		s = 129;
456*ce95e1b3SDavid du Colombier 		cput(s);
457*ce95e1b3SDavid du Colombier 		lcsize++;
458*ce95e1b3SDavid du Colombier 	}
459*ce95e1b3SDavid du Colombier 	if(debug['v'] || debug['L'])
460*ce95e1b3SDavid du Colombier 		Bprint(&bso, "lcsize = %ld\n", lcsize);
461*ce95e1b3SDavid du Colombier 	Bflush(&bso);
462*ce95e1b3SDavid du Colombier }
463*ce95e1b3SDavid du Colombier 
464*ce95e1b3SDavid du Colombier void
datblk(long s,long n,int str)465*ce95e1b3SDavid du Colombier datblk(long s, long n, int str)
466*ce95e1b3SDavid du Colombier {
467*ce95e1b3SDavid du Colombier 	Prog *p;
468*ce95e1b3SDavid du Colombier 	char *cast;
469*ce95e1b3SDavid du Colombier 	vlong d;
470*ce95e1b3SDavid du Colombier 	long l, fl, j;
471*ce95e1b3SDavid du Colombier 	int i, c;
472*ce95e1b3SDavid du Colombier 
473*ce95e1b3SDavid du Colombier 	memset(buf.dbuf, 0, n+100);
474*ce95e1b3SDavid du Colombier 	for(p = datap; p != P; p = p->link) {
475*ce95e1b3SDavid du Colombier 		curp = p;
476*ce95e1b3SDavid du Colombier 		if(str != (p->from.sym->type == SSTRING))
477*ce95e1b3SDavid du Colombier 			continue;
478*ce95e1b3SDavid du Colombier 		l = p->from.sym->value + p->from.offset - s;
479*ce95e1b3SDavid du Colombier 		c = p->reg;
480*ce95e1b3SDavid du Colombier 		i = 0;
481*ce95e1b3SDavid du Colombier 		if(l < 0) {
482*ce95e1b3SDavid du Colombier 			if(l+c <= 0)
483*ce95e1b3SDavid du Colombier 				continue;
484*ce95e1b3SDavid du Colombier 			while(l < 0) {
485*ce95e1b3SDavid du Colombier 				l++;
486*ce95e1b3SDavid du Colombier 				i++;
487*ce95e1b3SDavid du Colombier 			}
488*ce95e1b3SDavid du Colombier 		}
489*ce95e1b3SDavid du Colombier 		if(l >= n)
490*ce95e1b3SDavid du Colombier 			continue;
491*ce95e1b3SDavid du Colombier 		if(p->as != AINIT && p->as != ADYNT) {
492*ce95e1b3SDavid du Colombier 			for(j=l+(c-i)-1; j>=l; j--)
493*ce95e1b3SDavid du Colombier 				if(buf.dbuf[j]) {
494*ce95e1b3SDavid du Colombier 					print("%P\n", p);
495*ce95e1b3SDavid du Colombier 					diag("multiple initialization");
496*ce95e1b3SDavid du Colombier 					break;
497*ce95e1b3SDavid du Colombier 				}
498*ce95e1b3SDavid du Colombier 		}
499*ce95e1b3SDavid du Colombier 		switch(p->to.type) {
500*ce95e1b3SDavid du Colombier 		default:
501*ce95e1b3SDavid du Colombier 			diag("unknown mode in initialization\n%P", p);
502*ce95e1b3SDavid du Colombier 			break;
503*ce95e1b3SDavid du Colombier 
504*ce95e1b3SDavid du Colombier 		case D_FCONST:
505*ce95e1b3SDavid du Colombier 			switch(c) {
506*ce95e1b3SDavid du Colombier 			default:
507*ce95e1b3SDavid du Colombier 			case 4:
508*ce95e1b3SDavid du Colombier 				fl = ieeedtof(p->to.ieee);
509*ce95e1b3SDavid du Colombier 				cast = (char*)&fl;
510*ce95e1b3SDavid du Colombier 				for(; i<c; i++) {
511*ce95e1b3SDavid du Colombier 					buf.dbuf[l] = cast[fnuxi8[i]];
512*ce95e1b3SDavid du Colombier 					l++;
513*ce95e1b3SDavid du Colombier 				}
514*ce95e1b3SDavid du Colombier 				break;
515*ce95e1b3SDavid du Colombier 			case 8:
516*ce95e1b3SDavid du Colombier 				cast = (char*)p->to.ieee;
517*ce95e1b3SDavid du Colombier 				for(; i<c; i++) {
518*ce95e1b3SDavid du Colombier 					buf.dbuf[l] = cast[fnuxi8[i]];
519*ce95e1b3SDavid du Colombier 					l++;
520*ce95e1b3SDavid du Colombier 				}
521*ce95e1b3SDavid du Colombier 				break;
522*ce95e1b3SDavid du Colombier 			}
523*ce95e1b3SDavid du Colombier 			break;
524*ce95e1b3SDavid du Colombier 
525*ce95e1b3SDavid du Colombier 		case D_SCONST:
526*ce95e1b3SDavid du Colombier 			for(; i<c; i++) {
527*ce95e1b3SDavid du Colombier 				buf.dbuf[l] = p->to.sval[i];
528*ce95e1b3SDavid du Colombier 				l++;
529*ce95e1b3SDavid du Colombier 			}
530*ce95e1b3SDavid du Colombier 			break;
531*ce95e1b3SDavid du Colombier 
532*ce95e1b3SDavid du Colombier 		case D_VCONST:
533*ce95e1b3SDavid du Colombier 			d = *p->to.vval;
534*ce95e1b3SDavid du Colombier 			goto dconst;
535*ce95e1b3SDavid du Colombier 
536*ce95e1b3SDavid du Colombier 		case D_CONST:
537*ce95e1b3SDavid du Colombier 			d = p->to.offset;
538*ce95e1b3SDavid du Colombier 		dconst:
539*ce95e1b3SDavid du Colombier 			if(p->to.sym) {
540*ce95e1b3SDavid du Colombier 				switch(p->to.sym->type) {
541*ce95e1b3SDavid du Colombier 				case STEXT:
542*ce95e1b3SDavid du Colombier 				case SLEAF:
543*ce95e1b3SDavid du Colombier 				case SSTRING:
544*ce95e1b3SDavid du Colombier 					d += (p->to.sym->value + INITTEXT);
545*ce95e1b3SDavid du Colombier 					break;
546*ce95e1b3SDavid du Colombier 				case SDATA:
547*ce95e1b3SDavid du Colombier 				case SBSS:
548*ce95e1b3SDavid du Colombier 					d += (p->to.sym->value + INITDAT);
549*ce95e1b3SDavid du Colombier 					break;
550*ce95e1b3SDavid du Colombier 				}
551*ce95e1b3SDavid du Colombier 			}
552*ce95e1b3SDavid du Colombier 			cast = (char*)&d;
553*ce95e1b3SDavid du Colombier 			switch(c) {
554*ce95e1b3SDavid du Colombier 			default:
555*ce95e1b3SDavid du Colombier 				diag("bad nuxi %d %d\n%P", c, i, curp);
556*ce95e1b3SDavid du Colombier 				break;
557*ce95e1b3SDavid du Colombier 			case 1:
558*ce95e1b3SDavid du Colombier 				for(; i<c; i++) {
559*ce95e1b3SDavid du Colombier 					buf.dbuf[l] = cast[inuxi1[i]];
560*ce95e1b3SDavid du Colombier 					l++;
561*ce95e1b3SDavid du Colombier 				}
562*ce95e1b3SDavid du Colombier 				break;
563*ce95e1b3SDavid du Colombier 			case 2:
564*ce95e1b3SDavid du Colombier 				for(; i<c; i++) {
565*ce95e1b3SDavid du Colombier 					buf.dbuf[l] = cast[inuxi2[i]];
566*ce95e1b3SDavid du Colombier 					l++;
567*ce95e1b3SDavid du Colombier 				}
568*ce95e1b3SDavid du Colombier 				break;
569*ce95e1b3SDavid du Colombier 			case 4:
570*ce95e1b3SDavid du Colombier 				for(; i<c; i++) {
571*ce95e1b3SDavid du Colombier 					buf.dbuf[l] = cast[inuxi4[i]];
572*ce95e1b3SDavid du Colombier 					l++;
573*ce95e1b3SDavid du Colombier 				}
574*ce95e1b3SDavid du Colombier 				break;
575*ce95e1b3SDavid du Colombier 			case 8:
576*ce95e1b3SDavid du Colombier 				for(; i<c; i++) {
577*ce95e1b3SDavid du Colombier 					buf.dbuf[l] = cast[inuxi8[i]];
578*ce95e1b3SDavid du Colombier 					l++;
579*ce95e1b3SDavid du Colombier 				}
580*ce95e1b3SDavid du Colombier 				break;
581*ce95e1b3SDavid du Colombier 			}
582*ce95e1b3SDavid du Colombier 			break;
583*ce95e1b3SDavid du Colombier 		}
584*ce95e1b3SDavid du Colombier 		if(debug['d'] && i == c) {
585*ce95e1b3SDavid du Colombier 			Bprint(&bso, "%.8llux", l+s+INITDAT-c);
586*ce95e1b3SDavid du Colombier 			for(j = -c; j<0; j++)
587*ce95e1b3SDavid du Colombier 				Bprint(&bso, " %.2ux", ((uchar*)buf.dbuf)[l + j]);
588*ce95e1b3SDavid du Colombier 			Bprint(&bso, "\t%P\n", curp);
589*ce95e1b3SDavid du Colombier 		}
590*ce95e1b3SDavid du Colombier 	}
591*ce95e1b3SDavid du Colombier 	write(cout, buf.dbuf, n);
592*ce95e1b3SDavid du Colombier }
593*ce95e1b3SDavid du Colombier 
594*ce95e1b3SDavid du Colombier #define R(r) ((r)&0x1F)
595*ce95e1b3SDavid du Colombier #define OPX	(0x3 | o->op<<2)
596*ce95e1b3SDavid du Colombier #define OPF (OPX | o->func3<<12)
597*ce95e1b3SDavid du Colombier #define OP_R(rs1,rs2,rd)\
598*ce95e1b3SDavid du Colombier 	(OPF | rd<<7 | R(rs1)<<15 | R(rs2)<<20 | o->param<<25)
599*ce95e1b3SDavid du Colombier #define OP_RF(rs1,rs2,rd,rm)\
600*ce95e1b3SDavid du Colombier 	(OPX | rm<<12 | rd<<7 | R(rs1)<<15 | R(rs2)<<20 | o->param<<25)
601*ce95e1b3SDavid du Colombier #define OP_RO(rs1,rs2,rd)\
602*ce95e1b3SDavid du Colombier 	(0x3 | OOP<<2 | o->func3<<12 | rd<<7 | R(rs1)<<15 | R(rs2)<<20)
603*ce95e1b3SDavid du Colombier #define OP_ADD(rs1,rs2,rd)\
604*ce95e1b3SDavid du Colombier 	(0x3 | OOP<<2 | rd<<7 | R(rs1)<<15 | R(rs2)<<20)
605*ce95e1b3SDavid du Colombier #define OP_I(rs1,rd,imm)\
606*ce95e1b3SDavid du Colombier 	(OPF | rd<<7 | R(rs1)<<15 | (imm)<<20)
607*ce95e1b3SDavid du Colombier #define OP_FI(func3,rs1,rd,imm)\
608*ce95e1b3SDavid du Colombier 	(OPX | func3<<12 | rd<<7 | R(rs1)<<15 | (imm)<<20)
609*ce95e1b3SDavid du Colombier #define OP_S(rs1,rs2,imm)\
610*ce95e1b3SDavid du Colombier 	(OPF | (imm&0x1F)<<7 | R(rs1)<<15 | R(rs2)<<20 | (imm>>5)<<25)
611*ce95e1b3SDavid du Colombier #define OP_B(rs1,rs2,imm)\
612*ce95e1b3SDavid du Colombier 	(OPF | R(rs1)<<15 | R(rs2)<<20 | (imm&0x800)>>4 | (imm&0x1E)<<7 | \
613*ce95e1b3SDavid du Colombier 	 (imm&0x7E0)<<20 | (imm&0x1000)<<19)
614*ce95e1b3SDavid du Colombier #define OP_U(rd,imm)\
615*ce95e1b3SDavid du Colombier 	(0x3 | OLUI<<2 | rd<<7 | (imm&0xFFFFF000))
616*ce95e1b3SDavid du Colombier #define OP_UP(rd,imm)\
617*ce95e1b3SDavid du Colombier 	(0x3 | OAUIPC<<2 | rd<<7 | (imm&0xFFFFF000))
618*ce95e1b3SDavid du Colombier #define OP_J(rd,imm)\
619*ce95e1b3SDavid du Colombier 	(OPX | rd<<7 | (imm&0xff000) | (imm&0x800)<<9 | (imm&0x7FE)<<20 | (imm&0x100000)<<11)
620*ce95e1b3SDavid du Colombier 
621*ce95e1b3SDavid du Colombier /*
622*ce95e1b3SDavid du Colombier  * aflag: 0 - assemble to object file
623*ce95e1b3SDavid du Colombier  *        1 - return assembled instruction
624*ce95e1b3SDavid du Colombier  *        2 - first pass, return length of assembled instruction
625*ce95e1b3SDavid du Colombier  *        3 - later pass, return length of assembled instruction
626*ce95e1b3SDavid du Colombier  */
627*ce95e1b3SDavid du Colombier int
asmout(Prog * p,Optab * o,int aflag)628*ce95e1b3SDavid du Colombier asmout(Prog *p, Optab *o, int aflag)
629*ce95e1b3SDavid du Colombier {
630*ce95e1b3SDavid du Colombier 	vlong vv;
631*ce95e1b3SDavid du Colombier 	long o1, o2, o3, v;
632*ce95e1b3SDavid du Colombier 	int r;
633*ce95e1b3SDavid du Colombier 
634*ce95e1b3SDavid du Colombier 	o1 = 0;
635*ce95e1b3SDavid du Colombier 	o2 = 0;
636*ce95e1b3SDavid du Colombier 	o3 = 0;
637*ce95e1b3SDavid du Colombier 	r = p->reg;
638*ce95e1b3SDavid du Colombier 	if(r == NREG) switch(p->as){
639*ce95e1b3SDavid du Colombier 		case AMOVF:
640*ce95e1b3SDavid du Colombier 		case AMOVD:
641*ce95e1b3SDavid du Colombier 			if(p->from.type == D_FREG && p->to.type == D_FREG)
642*ce95e1b3SDavid du Colombier 				r = p->from.reg;
643*ce95e1b3SDavid du Colombier 			break;
644*ce95e1b3SDavid du Colombier 		case AMOV:
645*ce95e1b3SDavid du Colombier 		case AJMP:
646*ce95e1b3SDavid du Colombier 			r = REGZERO;
647*ce95e1b3SDavid du Colombier 			break;
648*ce95e1b3SDavid du Colombier 		case AJAL:
649*ce95e1b3SDavid du Colombier 			r = REGLINK;
650*ce95e1b3SDavid du Colombier 			break;
651*ce95e1b3SDavid du Colombier 		default:
652*ce95e1b3SDavid du Colombier 			r = p->to.reg;
653*ce95e1b3SDavid du Colombier 			break;
654*ce95e1b3SDavid du Colombier 	}
655*ce95e1b3SDavid du Colombier 	if(!debug['c'] && o->ctype){
656*ce95e1b3SDavid du Colombier 		o1 = asmcompressed(p, o, r, aflag == 2);
657*ce95e1b3SDavid du Colombier 		if(o1 != 0){
658*ce95e1b3SDavid du Colombier 			switch(aflag){
659*ce95e1b3SDavid du Colombier 			case 1:
660*ce95e1b3SDavid du Colombier 				return o1;
661*ce95e1b3SDavid du Colombier 			case 2:
662*ce95e1b3SDavid du Colombier 			case 3:
663*ce95e1b3SDavid du Colombier 				return 2;
664*ce95e1b3SDavid du Colombier 			}
665*ce95e1b3SDavid du Colombier 			if(debug['a']){
666*ce95e1b3SDavid du Colombier 				v = p->pc + INITTEXT;
667*ce95e1b3SDavid du Colombier 				Bprint(&bso, " %.8lux: %.4lux    \t%P\n", v, o1, p);
668*ce95e1b3SDavid du Colombier 			}
669*ce95e1b3SDavid du Colombier 			wputl(o1);
670*ce95e1b3SDavid du Colombier 			return 2;
671*ce95e1b3SDavid du Colombier 		}
672*ce95e1b3SDavid du Colombier 	}
673*ce95e1b3SDavid du Colombier 	if(aflag >= 2)
674*ce95e1b3SDavid du Colombier 		return o->size;
675*ce95e1b3SDavid du Colombier 	switch(o->type) {
676*ce95e1b3SDavid du Colombier 	default:
677*ce95e1b3SDavid du Colombier 		diag("unknown type %d", o->type);
678*ce95e1b3SDavid du Colombier 		if(!debug['a'])
679*ce95e1b3SDavid du Colombier 			prasm(p);
680*ce95e1b3SDavid du Colombier 		break;
681*ce95e1b3SDavid du Colombier 
682*ce95e1b3SDavid du Colombier 	case 0:		/* add S,[R,]D */
683*ce95e1b3SDavid du Colombier 		o1 = OP_R(r, p->from.reg, p->to.reg);
684*ce95e1b3SDavid du Colombier 		break;
685*ce95e1b3SDavid du Colombier 
686*ce95e1b3SDavid du Colombier 	case 1:		/* slli $I,[R,]D */
687*ce95e1b3SDavid du Colombier 		v = p->from.offset & 0x3F;
688*ce95e1b3SDavid du Colombier 		v |= (o->param<<5);
689*ce95e1b3SDavid du Colombier 		o1 = OP_I(r, p->to.reg, v);
690*ce95e1b3SDavid du Colombier 		break;
691*ce95e1b3SDavid du Colombier 
692*ce95e1b3SDavid du Colombier 	case 2:		/* addi $I,[R,]D */
693*ce95e1b3SDavid du Colombier 		v = p->from.offset;
694*ce95e1b3SDavid du Colombier 		if(v < -BIG || v >= BIG)
695*ce95e1b3SDavid du Colombier 			diag("imm out of range\n%P", p);
696*ce95e1b3SDavid du Colombier 		o1 = OP_I(r, p->to.reg, v);
697*ce95e1b3SDavid du Colombier 		break;
698*ce95e1b3SDavid du Colombier 
699*ce95e1b3SDavid du Colombier 	case 3:		/* beq S,[R,]L */
700*ce95e1b3SDavid du Colombier 		if(r == NREG)
701*ce95e1b3SDavid du Colombier 			r = REGZERO;
702*ce95e1b3SDavid du Colombier 		if(p->cond == P)
703*ce95e1b3SDavid du Colombier 			v = 0;
704*ce95e1b3SDavid du Colombier 		else
705*ce95e1b3SDavid du Colombier 			v = (p->cond->pc - pc);
706*ce95e1b3SDavid du Colombier 		if(v < -0x1000 || v >= 0x1000)
707*ce95e1b3SDavid du Colombier 			diag("branch out of range\n%P", p);
708*ce95e1b3SDavid du Colombier 		o1 = OP_B(r, p->from.reg, v);
709*ce95e1b3SDavid du Colombier 		break;
710*ce95e1b3SDavid du Colombier 
711*ce95e1b3SDavid du Colombier 	case 4:		/* jal	[D,]L */
712*ce95e1b3SDavid du Colombier 		if(p->cond == P)
713*ce95e1b3SDavid du Colombier 			v = 0;
714*ce95e1b3SDavid du Colombier 		else
715*ce95e1b3SDavid du Colombier 			v = (p->cond->pc - pc);
716*ce95e1b3SDavid du Colombier 		if(v < -0x100000 || v >= 0x100000)
717*ce95e1b3SDavid du Colombier 			diag("jump out of range\n%P", p);
718*ce95e1b3SDavid du Colombier 		o1 = OP_J(r, v);
719*ce95e1b3SDavid du Colombier 		break;
720*ce95e1b3SDavid du Colombier 
721*ce95e1b3SDavid du Colombier 	case 5:		/* jalr [D,]I(S) */
722*ce95e1b3SDavid du Colombier 		v = regoff(&p->to);
723*ce95e1b3SDavid du Colombier 		if(v < -BIG || v >= BIG)
724*ce95e1b3SDavid du Colombier 			diag("imm out of range\n%P", p);
725*ce95e1b3SDavid du Colombier 		o1 = OP_I(classreg(&p->to), r, v);
726*ce95e1b3SDavid du Colombier 		break;
727*ce95e1b3SDavid du Colombier 
728*ce95e1b3SDavid du Colombier 	case 6:		/* sb	R,I(S) */
729*ce95e1b3SDavid du Colombier 		v = regoff(&p->to);
730*ce95e1b3SDavid du Colombier 		r = classreg(&p->to);
731*ce95e1b3SDavid du Colombier 		if(v < -BIG || v >= BIG)
732*ce95e1b3SDavid du Colombier 			diag("imm out of range\n%P", p);
733*ce95e1b3SDavid du Colombier 		o1 = OP_S(r, p->from.reg, v);
734*ce95e1b3SDavid du Colombier 		break;
735*ce95e1b3SDavid du Colombier 
736*ce95e1b3SDavid du Colombier 	case 7:		/* lb	I(S),D */
737*ce95e1b3SDavid du Colombier 		v = regoff(&p->from);
738*ce95e1b3SDavid du Colombier 		r = classreg(&p->from);
739*ce95e1b3SDavid du Colombier 		if(v < -BIG || v >= BIG)
740*ce95e1b3SDavid du Colombier 			diag("imm out of range\n%P", p);
741*ce95e1b3SDavid du Colombier 		o1 = OP_I(r, p->to.reg, v);
742*ce95e1b3SDavid du Colombier 		break;
743*ce95e1b3SDavid du Colombier 
744*ce95e1b3SDavid du Colombier 	case 8:		/* lui	I,D */
745*ce95e1b3SDavid du Colombier 		v = p->from.offset;
746*ce95e1b3SDavid du Colombier 		o1 = OP_U(p->to.reg, v);
747*ce95e1b3SDavid du Colombier 		break;
748*ce95e1b3SDavid du Colombier 
749*ce95e1b3SDavid du Colombier 	case 9:		/* lui	I1,D; addi I0,D */
750*ce95e1b3SDavid du Colombier 		v = regoff(&p->from);
751*ce95e1b3SDavid du Colombier 		if(thechar == 'j' && v >= 0x7ffff800){
752*ce95e1b3SDavid du Colombier 			/* awkward edge case */
753*ce95e1b3SDavid du Colombier 			o1 = OP_U(p->to.reg, -v);
754*ce95e1b3SDavid du Colombier 			v &= 0xFFF;
755*ce95e1b3SDavid du Colombier 			o2 = OP_FI(4, p->to.reg, p->to.reg, v);	/* xori */
756*ce95e1b3SDavid du Colombier 			break;
757*ce95e1b3SDavid du Colombier 		}
758*ce95e1b3SDavid du Colombier 		if(v & 0x800)
759*ce95e1b3SDavid du Colombier 			v += 0x1000;
760*ce95e1b3SDavid du Colombier 		o1 = OP_U(p->to.reg, v);
761*ce95e1b3SDavid du Colombier 		v &= 0xFFF;
762*ce95e1b3SDavid du Colombier 		o2 = OP_I(p->to.reg, p->to.reg, v);
763*ce95e1b3SDavid du Colombier 		break;
764*ce95e1b3SDavid du Colombier 
765*ce95e1b3SDavid du Colombier 	case 10:	/* sign extend */
766*ce95e1b3SDavid du Colombier 		if(p->as == AMOVBU) {
767*ce95e1b3SDavid du Colombier 			o1 = OP_I(p->from.reg, p->to.reg, o->param);
768*ce95e1b3SDavid du Colombier 			break;
769*ce95e1b3SDavid du Colombier 		}
770*ce95e1b3SDavid du Colombier 		v = o->param;
771*ce95e1b3SDavid du Colombier 		if(thechar == 'j')
772*ce95e1b3SDavid du Colombier 			v += 32;
773*ce95e1b3SDavid du Colombier 		o1 = OP_FI(1, p->from.reg, p->to.reg, v & 0x3F);	/* slli */
774*ce95e1b3SDavid du Colombier 		o2 = OP_I(p->to.reg, p->to.reg, v);	/* srli or srai */
775*ce95e1b3SDavid du Colombier 		break;
776*ce95e1b3SDavid du Colombier 
777*ce95e1b3SDavid du Colombier 	case 11:		/* addi $I,R,D */
778*ce95e1b3SDavid du Colombier 		v = regoff(&p->from);
779*ce95e1b3SDavid du Colombier 		if(v < -BIG || v >= BIG)
780*ce95e1b3SDavid du Colombier 			diag("imm out of range\n%P", p);
781*ce95e1b3SDavid du Colombier 		o1 = OP_I(classreg(&p->from), p->to.reg, v);
782*ce95e1b3SDavid du Colombier 		break;
783*ce95e1b3SDavid du Colombier 
784*ce95e1b3SDavid du Colombier 	case 12:		/* mov r,lext => lui/auipc I1,T; sb r,I0(T) */
785*ce95e1b3SDavid du Colombier 		v = regoff(&p->to);
786*ce95e1b3SDavid du Colombier 		if(thechar == 'j'){
787*ce95e1b3SDavid du Colombier 			vv = v + INITDAT + BIG - INITTEXT - pc;
788*ce95e1b3SDavid du Colombier 			v = (long)vv;
789*ce95e1b3SDavid du Colombier 			if(v != vv || (v&~0x7FF) == 0x7FFFF800)
790*ce95e1b3SDavid du Colombier 				diag("address out of range\n%P", p);
791*ce95e1b3SDavid du Colombier 		}else
792*ce95e1b3SDavid du Colombier 			v += INITDAT + BIG;
793*ce95e1b3SDavid du Colombier 		if(v & 0x800)
794*ce95e1b3SDavid du Colombier 			v += 0x1000;
795*ce95e1b3SDavid du Colombier 		o1 = thechar == 'j' ? OP_UP(REGTMP, v) : OP_U(REGTMP, v);
796*ce95e1b3SDavid du Colombier 		v &= 0xFFF;
797*ce95e1b3SDavid du Colombier 		o2 = OP_S(REGTMP, p->from.reg, v);
798*ce95e1b3SDavid du Colombier 		break;
799*ce95e1b3SDavid du Colombier 
800*ce95e1b3SDavid du Colombier 	case 13:		/* mov lext, r => lui/auipc I1,T; lb r,I0(T) */
801*ce95e1b3SDavid du Colombier 		v = regoff(&p->from);
802*ce95e1b3SDavid du Colombier 		if(thechar == 'j'){
803*ce95e1b3SDavid du Colombier 			vv = v + INITDAT + BIG - INITTEXT - pc;
804*ce95e1b3SDavid du Colombier 			v = (long)vv;
805*ce95e1b3SDavid du Colombier 			if(v != vv || (v&~0x7FF) == 0x7FFFF800)
806*ce95e1b3SDavid du Colombier 				diag("address out of range\n%P", p);
807*ce95e1b3SDavid du Colombier 		}else
808*ce95e1b3SDavid du Colombier 				v += INITDAT + BIG;
809*ce95e1b3SDavid du Colombier 		if(v & 0x800)
810*ce95e1b3SDavid du Colombier 			v += 0x1000;
811*ce95e1b3SDavid du Colombier 		o1 = thechar == 'j' ? OP_UP(REGTMP, v) : OP_U(REGTMP, v);
812*ce95e1b3SDavid du Colombier 		v &= 0xFFF;
813*ce95e1b3SDavid du Colombier 		o2 = OP_I(REGTMP, p->to.reg, v);
814*ce95e1b3SDavid du Colombier 		break;
815*ce95e1b3SDavid du Colombier 
816*ce95e1b3SDavid du Colombier 	case 14:		/* op $lcon,[r,]d => lui L1,T; addi $L0,T,T; op T,r,d */
817*ce95e1b3SDavid du Colombier 		v = regoff(&p->from);
818*ce95e1b3SDavid du Colombier 		if(p->as == AMOVW || p->as == AMOV)
819*ce95e1b3SDavid du Colombier 			r = classreg(&p->from);
820*ce95e1b3SDavid du Colombier 		if(thechar == 'j' && v >= 0x7ffff800){
821*ce95e1b3SDavid du Colombier 			/* awkward edge case */
822*ce95e1b3SDavid du Colombier 			o1 = OP_U(p->to.reg, -v);
823*ce95e1b3SDavid du Colombier 			v &= 0xFFF;
824*ce95e1b3SDavid du Colombier 			o2 = OP_FI(4, p->to.reg, p->to.reg, v);	/* xori */
825*ce95e1b3SDavid du Colombier 		}else{
826*ce95e1b3SDavid du Colombier 			if(v & 0x800)
827*ce95e1b3SDavid du Colombier 				v += 0x1000;
828*ce95e1b3SDavid du Colombier 			o1 = OP_U(REGTMP, v);
829*ce95e1b3SDavid du Colombier 			v &= 0xFFF;
830*ce95e1b3SDavid du Colombier 			o2 = OP_FI(0, REGTMP, REGTMP, v);	/* addi */
831*ce95e1b3SDavid du Colombier 		}
832*ce95e1b3SDavid du Colombier 		o3 = OP_RO(r, REGTMP, p->to.reg);
833*ce95e1b3SDavid du Colombier 		break;
834*ce95e1b3SDavid du Colombier 
835*ce95e1b3SDavid du Colombier 	case 15:		/* mov r,L(s) => lui L1,T; add s,T,T; sb r,L0(T) */
836*ce95e1b3SDavid du Colombier 		v = regoff(&p->to);
837*ce95e1b3SDavid du Colombier 		r = classreg(&p->to);
838*ce95e1b3SDavid du Colombier 		if(v & 0x800)
839*ce95e1b3SDavid du Colombier 			v += 0x1000;
840*ce95e1b3SDavid du Colombier 		o1 = OP_U(REGTMP, v);
841*ce95e1b3SDavid du Colombier 		v &= 0xFFF;
842*ce95e1b3SDavid du Colombier 		o2 = OP_ADD(r, REGTMP, REGTMP);
843*ce95e1b3SDavid du Colombier 		o3 = OP_S(REGTMP, p->from.reg, v);
844*ce95e1b3SDavid du Colombier 		break;
845*ce95e1b3SDavid du Colombier 
846*ce95e1b3SDavid du Colombier 	case 16:		/* mov L(s),r => lui L1,T; add s,T,T; lb r,L0(T) */
847*ce95e1b3SDavid du Colombier 		v = regoff(&p->from);
848*ce95e1b3SDavid du Colombier 		r = classreg(&p->from);
849*ce95e1b3SDavid du Colombier 		if(v & 0x800)
850*ce95e1b3SDavid du Colombier 			v += 0x1000;
851*ce95e1b3SDavid du Colombier 		o1 = OP_U(REGTMP, v);
852*ce95e1b3SDavid du Colombier 		v &= 0xFFF;
853*ce95e1b3SDavid du Colombier 		o2 = OP_ADD(r, REGTMP, REGTMP);
854*ce95e1b3SDavid du Colombier 		o3 = OP_I(REGTMP, p->to.reg, v);
855*ce95e1b3SDavid du Colombier 		break;
856*ce95e1b3SDavid du Colombier 
857*ce95e1b3SDavid du Colombier 	case 17:	/* fcvt S,D */
858*ce95e1b3SDavid du Colombier 		v = 7;	/* dynamic rounding mode */
859*ce95e1b3SDavid du Colombier 		if(o->a3 == C_REG)	/* convert to int? */
860*ce95e1b3SDavid du Colombier 			v = 1;	/* round towards zero */
861*ce95e1b3SDavid du Colombier 		o1 = OP_RF(p->from.reg, o->func3, p->to.reg, v);
862*ce95e1b3SDavid du Colombier 		break;
863*ce95e1b3SDavid du Colombier 
864*ce95e1b3SDavid du Colombier 	case 18:	/* lui L1, T; jal [r,]L0(T) */
865*ce95e1b3SDavid du Colombier 		if(p->cond == P)
866*ce95e1b3SDavid du Colombier 			v = 0;
867*ce95e1b3SDavid du Colombier 		else
868*ce95e1b3SDavid du Colombier 			v = p->cond->pc;
869*ce95e1b3SDavid du Colombier 		if(thechar == 'j'){
870*ce95e1b3SDavid du Colombier 			vv = v + INITTEXT;
871*ce95e1b3SDavid du Colombier 			v = (long)vv;
872*ce95e1b3SDavid du Colombier 			if(v != vv || (v&~0x7FF) == 0x7FFFF800)
873*ce95e1b3SDavid du Colombier 				diag("branch out of range\n%P", p);
874*ce95e1b3SDavid du Colombier 		}else
875*ce95e1b3SDavid du Colombier 			v += INITTEXT;
876*ce95e1b3SDavid du Colombier 		if(v & 0x800)
877*ce95e1b3SDavid du Colombier 			v += 0x1000;
878*ce95e1b3SDavid du Colombier 		o1 = thechar == 'j' ? OP_UP(REGTMP, v) : OP_U(REGTMP, v);
879*ce95e1b3SDavid du Colombier 		v &= 0xFFF;
880*ce95e1b3SDavid du Colombier 		o2 = OP_I(REGTMP, r, v);
881*ce95e1b3SDavid du Colombier 		break;
882*ce95e1b3SDavid du Colombier 
883*ce95e1b3SDavid du Colombier 	case 19:	/* addiw $0, rs, rd */
884*ce95e1b3SDavid du Colombier 		v = 0;
885*ce95e1b3SDavid du Colombier 		o1 = OP_I(p->from.reg, p->to.reg, v);
886*ce95e1b3SDavid du Colombier 		break;
887*ce95e1b3SDavid du Colombier 
888*ce95e1b3SDavid du Colombier 	case 20:	/* lui/auipc I1,D; addi I0; D */
889*ce95e1b3SDavid du Colombier 		if(thechar == 'j'){
890*ce95e1b3SDavid du Colombier 			vv = regoff(&p->from) + instoffx - (pc + INITTEXT);
891*ce95e1b3SDavid du Colombier 			v = (long)vv;
892*ce95e1b3SDavid du Colombier 			if(v != vv || (v&~0x7FF) == 0x7FFFF800)
893*ce95e1b3SDavid du Colombier 				diag("address %llux out of range\n%P", regoff(&p->from) + instoffx, p);
894*ce95e1b3SDavid du Colombier 		}else{
895*ce95e1b3SDavid du Colombier 			v = regoff(&p->from) + instoffx;
896*ce95e1b3SDavid du Colombier 		}
897*ce95e1b3SDavid du Colombier 		if(v & 0x800)
898*ce95e1b3SDavid du Colombier 			v += 0x1000;
899*ce95e1b3SDavid du Colombier 		o1 = thechar == 'j' ? OP_UP(p->to.reg, v) : OP_U(p->to.reg, v);
900*ce95e1b3SDavid du Colombier 		v &= 0xFFF;
901*ce95e1b3SDavid du Colombier 		o2 = OP_I(p->to.reg, p->to.reg, v);
902*ce95e1b3SDavid du Colombier 		break;
903*ce95e1b3SDavid du Colombier 
904*ce95e1b3SDavid du Colombier 	case 21:	/* lui I,D; s[lr]ai N,D */
905*ce95e1b3SDavid du Colombier 		vv = *p->from.vval;
906*ce95e1b3SDavid du Colombier 		v = vconshift(vv);
907*ce95e1b3SDavid du Colombier 		if(v < 0)
908*ce95e1b3SDavid du Colombier 			diag("64 bit constant error:\n%P", p);
909*ce95e1b3SDavid du Colombier 		if(v < 12)
910*ce95e1b3SDavid du Colombier 			vv <<= 12 - v;
911*ce95e1b3SDavid du Colombier 		else
912*ce95e1b3SDavid du Colombier 			vv >>= v - 12;
913*ce95e1b3SDavid du Colombier 		o1 = OP_U(p->to.reg, (long)vv);
914*ce95e1b3SDavid du Colombier 		if (v > 12)
915*ce95e1b3SDavid du Colombier 			o2 = OP_FI(1, p->to.reg, p->to.reg, v - 12);	/* slli */
916*ce95e1b3SDavid du Colombier 		else
917*ce95e1b3SDavid du Colombier 			o2 = OP_I(p->to.reg, p->to.reg, 12 - v);	/* srai */
918*ce95e1b3SDavid du Colombier 		break;
919*ce95e1b3SDavid du Colombier 
920*ce95e1b3SDavid du Colombier 	case 22:	/* CSRRx C, rs, rd */
921*ce95e1b3SDavid du Colombier 		v = p->from.offset & 0xFFF;
922*ce95e1b3SDavid du Colombier 		o1 = OP_I(p->reg, p->to.reg, v);
923*ce95e1b3SDavid du Colombier 		break;
924*ce95e1b3SDavid du Colombier 
925*ce95e1b3SDavid du Colombier 	case 24:		/* SYS */
926*ce95e1b3SDavid du Colombier 		v = p->to.offset & 0xFFF;
927*ce95e1b3SDavid du Colombier 		o1 = OP_I(0, 0, v);
928*ce95e1b3SDavid du Colombier 		break;
929*ce95e1b3SDavid du Colombier 
930*ce95e1b3SDavid du Colombier 	case 25:		/* word $x */
931*ce95e1b3SDavid du Colombier 		o1 = regoff(&p->to);
932*ce95e1b3SDavid du Colombier 		break;
933*ce95e1b3SDavid du Colombier 
934*ce95e1b3SDavid du Colombier 	case 26:		/* pseudo ops */
935*ce95e1b3SDavid du Colombier 		break;
936*ce95e1b3SDavid du Colombier 	}
937*ce95e1b3SDavid du Colombier 	if(aflag)
938*ce95e1b3SDavid du Colombier 		return o1;
939*ce95e1b3SDavid du Colombier 	v = p->pc + INITTEXT;
940*ce95e1b3SDavid du Colombier 	switch(o->size) {
941*ce95e1b3SDavid du Colombier 	default:
942*ce95e1b3SDavid du Colombier 		if(debug['a'])
943*ce95e1b3SDavid du Colombier 			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
944*ce95e1b3SDavid du Colombier 		break;
945*ce95e1b3SDavid du Colombier 	case 4:
946*ce95e1b3SDavid du Colombier 		if(debug['a'])
947*ce95e1b3SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
948*ce95e1b3SDavid du Colombier 		lputl(o1);
949*ce95e1b3SDavid du Colombier 		break;
950*ce95e1b3SDavid du Colombier 	case 8:
951*ce95e1b3SDavid du Colombier 		if(debug['a'])
952*ce95e1b3SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
953*ce95e1b3SDavid du Colombier 		lputl(o1);
954*ce95e1b3SDavid du Colombier 		lputl(o2);
955*ce95e1b3SDavid du Colombier 		break;
956*ce95e1b3SDavid du Colombier 	case 12:
957*ce95e1b3SDavid du Colombier 		if(debug['a'])
958*ce95e1b3SDavid du Colombier 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
959*ce95e1b3SDavid du Colombier 		lputl(o1);
960*ce95e1b3SDavid du Colombier 		lputl(o2);
961*ce95e1b3SDavid du Colombier 		lputl(o3);
962*ce95e1b3SDavid du Colombier 		break;
963*ce95e1b3SDavid du Colombier 	}
964*ce95e1b3SDavid du Colombier 	return o->size;
965*ce95e1b3SDavid du Colombier }
966*ce95e1b3SDavid du Colombier 
967