xref: /plan9-contrib/sys/src/cmd/6l/asm.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
1 #include	"l.h"
2 
3 #define	Dbufslop	100
4 
5 #define PADDR(a)	((a) & ~0xfffffffff0000000ull)
6 
7 vlong
entryvalue(void)8 entryvalue(void)
9 {
10 	char *a;
11 	Sym *s;
12 
13 	a = INITENTRY;
14 	if(*a >= '0' && *a <= '9')
15 		return atolwhex(a);
16 	s = lookup(a, 0);
17 	if(s->type == 0)
18 		return INITTEXT;
19 	switch(s->type) {
20 	case STEXT:
21 		break;
22 	case SDATA:
23 		if(dlm)
24 			return s->value+INITDAT;
25 	default:
26 		diag("entry not text: %s", s->name);
27 	}
28 	return s->value;
29 }
30 
31 /* these need to take long arguments to be compatible with elf.c */
32 void
wputl(long w)33 wputl(long w)
34 {
35 	cput(w);
36 	cput(w>>8);
37 }
38 
39 void
wput(long w)40 wput(long w)
41 {
42 	cput(w>>8);
43 	cput(w);
44 }
45 
46 void
lput(long l)47 lput(long l)
48 {
49 	cput(l>>24);
50 	cput(l>>16);
51 	cput(l>>8);
52 	cput(l);
53 }
54 
55 void
llput(vlong v)56 llput(vlong v)
57 {
58 	lput(v>>32);
59 	lput(v);
60 }
61 
62 void
lputl(long l)63 lputl(long l)
64 {
65 	cput(l);
66 	cput(l>>8);
67 	cput(l>>16);
68 	cput(l>>24);
69 }
70 
71 void
llputl(vlong v)72 llputl(vlong v)
73 {
74 	lputl(v);
75 	lputl(v>>32);
76 }
77 
78 void
strnput(char * s,int n)79 strnput(char *s, int n)
80 {
81 	for(; *s && n > 0; s++){
82 		cput(*s);
83 		n--;
84 	}
85 	while(n > 0){
86 		cput(0);
87 		n--;
88 	}
89 }
90 
91 void
asmb(void)92 asmb(void)
93 {
94 	Prog *p;
95 	long v, magic;
96 	int a;
97 	uchar *op1;
98 	vlong vl;
99 
100 	if(debug['v'])
101 		Bprint(&bso, "%5.2f asmb\n", cputime());
102 	Bflush(&bso);
103 
104 	seek(cout, HEADR, 0);
105 	pc = INITTEXT;
106 	curp = firstp;
107 	for(p = firstp; p != P; p = p->link) {
108 		if(p->as == ATEXT)
109 			curtext = p;
110 		if(p->pc != pc) {
111 			if(!debug['a'])
112 				print("%P\n", curp);
113 			diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
114 			pc = p->pc;
115 		}
116 		curp = p;
117 		asmins(p);
118 		a = (andptr - and);
119 		if(cbc < a)
120 			cflush();
121 		if(debug['a']) {
122 			Bprint(&bso, pcstr, pc);
123 			for(op1 = and; op1 < andptr; op1++)
124 				Bprint(&bso, "%.2ux", *op1 & 0xff);
125 			Bprint(&bso, "\t%P\n", curp);
126 		}
127 		if(dlm) {
128 			if(p->as == ATEXT)
129 				reloca = nil;
130 			else if(reloca != nil)
131 				diag("reloc failure: %P", curp);
132 		}
133 		memmove(cbp, and, a);
134 		cbp += a;
135 		pc += a;
136 		cbc -= a;
137 	}
138 	cflush();
139 	switch(HEADTYPE) {
140 	default:
141 		diag("unknown header type %ld", HEADTYPE);
142 	case 2:
143 	case 5:
144 	case 6:
145 		seek(cout, HEADR+textsize, 0);
146 		break;
147 	}
148 
149 	if(debug['v'])
150 		Bprint(&bso, "%5.2f datblk\n", cputime());
151 	Bflush(&bso);
152 
153 	if(dlm){
154 		char buf[8];
155 
156 		write(cout, buf, INITDAT-textsize);
157 		textsize = INITDAT;
158 	}
159 
160 	for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
161 		if(datsize-v > sizeof(buf)-Dbufslop)
162 			datblk(v, sizeof(buf)-Dbufslop);
163 		else
164 			datblk(v, datsize-v);
165 	}
166 
167 	symsize = 0;
168 	spsize = 0;
169 	lcsize = 0;
170 	if(!debug['s']) {
171 		if(debug['v'])
172 			Bprint(&bso, "%5.2f sym\n", cputime());
173 		Bflush(&bso);
174 		switch(HEADTYPE) {
175 		default:
176 		case 2:
177 		case 5:
178 		case 6:
179 			seek(cout, HEADR+textsize+datsize, 0);
180 			break;
181 		}
182 		if(!debug['s'])
183 			asmsym();
184 		if(debug['v'])
185 			Bprint(&bso, "%5.2f sp\n", cputime());
186 		Bflush(&bso);
187 		if(debug['v'])
188 			Bprint(&bso, "%5.2f pc\n", cputime());
189 		Bflush(&bso);
190 		if(!debug['s'])
191 			asmlc();
192 		if(dlm)
193 			asmdyn();
194 		cflush();
195 	}
196 	else if(dlm){
197 		seek(cout, HEADR+textsize+datsize, 0);
198 		asmdyn();
199 		cflush();
200 	}
201 	if(debug['v'])
202 		Bprint(&bso, "%5.2f headr\n", cputime());
203 	Bflush(&bso);
204 	seek(cout, 0L, 0);
205 	switch(HEADTYPE) {
206 	default:
207 	case 2:	/* plan9 */
208 		magic = 4*26*26+7;
209 		magic |= 0x00008000;		/* fat header */
210 		if(dlm)
211 			magic |= 0x80000000;	/* dlm */
212 		lput(magic);			/* magic */
213 		lput(textsize);			/* sizes */
214 		lput(datsize);
215 		lput(bsssize);
216 		lput(symsize);			/* nsyms */
217 		vl = entryvalue();
218 		lput(PADDR(vl));		/* va of entry */
219 		lput(spsize);			/* sp offsets */
220 		lput(lcsize);			/* line offsets */
221 		llput(vl);			/* va of entry */
222 		break;
223 	case 5:
224 		elf32(debug['8']? I386: AMD64, ELFDATA2LSB, 0, nil);
225 		break;
226 	case 6:
227 		elf64(AMD64, ELFDATA2LSB, 0, nil);
228 		break;
229 	}
230 	cflush();
231 }
232 
233 void
cflush(void)234 cflush(void)
235 {
236 	int n;
237 
238 	n = sizeof(buf.cbuf) - cbc;
239 	if(n)
240 		write(cout, buf.cbuf, n);
241 	cbp = buf.cbuf;
242 	cbc = sizeof(buf.cbuf);
243 }
244 
245 void
datblk(long s,long n)246 datblk(long s, long n)
247 {
248 	Prog *p;
249 	uchar *cast;
250 	long l, fl, j;
251 	vlong o;
252 	int i, c;
253 
254 	memset(buf.dbuf, 0, n+Dbufslop);
255 	for(p = datap; p != P; p = p->link) {
256 		curp = p;
257 		l = p->from.sym->value + p->from.offset - s;
258 		c = p->from.scale;
259 		i = 0;
260 		if(l < 0) {
261 			if(l+c <= 0)
262 				continue;
263 			while(l < 0) {
264 				l++;
265 				i++;
266 			}
267 		}
268 		if(l >= n)
269 			continue;
270 		if(p->as != AINIT && p->as != ADYNT) {
271 			for(j=l+(c-i)-1; j>=l; j--)
272 				if(buf.dbuf[j]) {
273 					print("%P\n", p);
274 					diag("multiple initialization");
275 					break;
276 				}
277 		}
278 		switch(p->to.type) {
279 		case D_FCONST:
280 			switch(c) {
281 			default:
282 			case 4:
283 				fl = ieeedtof(&p->to.ieee);
284 				cast = (uchar*)&fl;
285 				if(debug['a'] && i == 0) {
286 					Bprint(&bso, pcstr, l+s+INITDAT);
287 					for(j=0; j<c; j++)
288 						Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
289 					Bprint(&bso, "\t%P\n", curp);
290 				}
291 				for(; i<c; i++) {
292 					buf.dbuf[l] = cast[fnuxi4[i]];
293 					l++;
294 				}
295 				break;
296 			case 8:
297 				cast = (uchar*)&p->to.ieee;
298 				if(debug['a'] && i == 0) {
299 					Bprint(&bso, pcstr, l+s+INITDAT);
300 					for(j=0; j<c; j++)
301 						Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
302 					Bprint(&bso, "\t%P\n", curp);
303 				}
304 				for(; i<c; i++) {
305 					buf.dbuf[l] = cast[fnuxi8[i]];
306 					l++;
307 				}
308 				break;
309 			}
310 			break;
311 
312 		case D_SCONST:
313 			if(debug['a'] && i == 0) {
314 				Bprint(&bso, pcstr, l+s+INITDAT);
315 				for(j=0; j<c; j++)
316 					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
317 				Bprint(&bso, "\t%P\n", curp);
318 			}
319 			for(; i<c; i++) {
320 				buf.dbuf[l] = p->to.scon[i];
321 				l++;
322 			}
323 			break;
324 		default:
325 			o = p->to.offset;
326 			if(p->to.type == D_ADDR) {
327 				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
328 					diag("DADDR type%P", p);
329 				if(p->to.sym) {
330 					if(p->to.sym->type == SUNDEF)
331 						ckoff(p->to.sym, o);
332 					o += p->to.sym->value;
333 					if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
334 						o += INITDAT;
335 					if(dlm)
336 						dynreloc(p->to.sym, l+s+INITDAT, 1);
337 				}
338 			}
339 			fl = o;
340 			cast = (uchar*)&fl;
341 			switch(c) {
342 			default:
343 				diag("bad nuxi %d %d\n%P", c, i, curp);
344 				break;
345 			case 1:
346 				if(debug['a'] && i == 0) {
347 					Bprint(&bso, pcstr, l+s+INITDAT);
348 					for(j=0; j<c; j++)
349 						Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
350 					Bprint(&bso, "\t%P\n", curp);
351 				}
352 				for(; i<c; i++) {
353 					buf.dbuf[l] = cast[inuxi1[i]];
354 					l++;
355 				}
356 				break;
357 			case 2:
358 				if(debug['a'] && i == 0) {
359 					Bprint(&bso, pcstr, l+s+INITDAT);
360 					for(j=0; j<c; j++)
361 						Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
362 					Bprint(&bso, "\t%P\n", curp);
363 				}
364 				for(; i<c; i++) {
365 					buf.dbuf[l] = cast[inuxi2[i]];
366 					l++;
367 				}
368 				break;
369 			case 4:
370 				if(debug['a'] && i == 0) {
371 					Bprint(&bso, pcstr, l+s+INITDAT);
372 					for(j=0; j<c; j++)
373 						Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
374 					Bprint(&bso, "\t%P\n", curp);
375 				}
376 				for(; i<c; i++) {
377 					buf.dbuf[l] = cast[inuxi4[i]];
378 					l++;
379 				}
380 				break;
381 			case 8:
382 				cast = (uchar*)&o;
383 				if(debug['a'] && i == 0) {
384 					Bprint(&bso, pcstr, l+s+INITDAT);
385 					for(j=0; j<c; j++)
386 						Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
387 					Bprint(&bso, "\t%P\n", curp);
388 				}
389 				for(; i<c; i++) {
390 					buf.dbuf[l] = cast[inuxi8[i]];
391 					l++;
392 				}
393 				break;
394 			}
395 			break;
396 		}
397 	}
398 	write(cout, buf.dbuf, n);
399 }
400 
401 vlong
rnd(vlong v,vlong r)402 rnd(vlong v, vlong r)
403 {
404 	vlong c;
405 
406 	if(r <= 0)
407 		return v;
408 	v += r - 1;
409 	c = v % r;
410 	if(c < 0)
411 		c += r;
412 	v -= c;
413 	return v;
414 }
415