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