xref: /inferno-os/utils/6l/asm.c (revision e57c7e16a3789cd4de1a3c2560d49b1ee39cd10a)
1 #include	"l.h"
2 
3 #define	Dbufslop	100
4 
5 #define PADDR(a)	((ulong)(a) & ~0x80000000)
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 		wputl(62);			/* machine = AMD64 */
234 		lputl(1L);			/* version = CURRENT */
235 		lputl(PADDR(entryvalue()));	/* entry vaddr */
236 		lputl(52L);			/* offset to first phdr */
237 		lputl(0L);			/* offset to first shdr */
238 		lputl(0L);			/* processor specific flags */
239 		wputl(52);			/* Ehdr size */
240 		wputl(32);			/* Phdr size */
241 		wputl(3);			/* # of Phdrs */
242 		wputl(0);			/* Shdr size */
243 		wputl(0);			/* # of Shdrs */
244 		wputl(0);			/* Shdr string size */
245 
246 		lputl(1L);			/* text - type = PT_LOAD */
247 		lputl(HEADR);			/* file offset */
248 		lputl(INITTEXT);		/* vaddr */
249 		lputl(PADDR(INITTEXT));		/* paddr */
250 		lputl(textsize);		/* file size */
251 		lputl(textsize);		/* memory size */
252 		lputl(0x05L);			/* protections = RX */
253 		lputl(INITRND);			/* alignment */
254 
255 		lputl(1L);			/* data - type = PT_LOAD */
256 		lputl(HEADR+textsize);		/* file offset */
257 		lputl(INITDAT);			/* vaddr */
258 		lputl(PADDR(INITDAT));		/* paddr */
259 		lputl(datsize);			/* file size */
260 		lputl(datsize+bsssize);		/* memory size */
261 		lputl(0x06L);			/* protections = RW */
262 		lputl(INITRND);			/* alignment */
263 
264 		lputl(0L);			/* data - type = PT_NULL */
265 		lputl(HEADR+textsize+datsize);	/* file offset */
266 		lputl(0L);
267 		lputl(0L);
268 		lputl(symsize);			/* symbol table size */
269 		lputl(lcsize);			/* line number size */
270 		lputl(0x04L);			/* protections = R */
271 		lputl(0x04L);			/* alignment */
272 		break;
273 	}
274 	cflush();
275 }
276 
277 void
278 cflush(void)
279 {
280 	int n;
281 
282 	n = sizeof(buf.cbuf) - cbc;
283 	if(n)
284 		write(cout, buf.cbuf, n);
285 	cbp = buf.cbuf;
286 	cbc = sizeof(buf.cbuf);
287 }
288 
289 void
290 datblk(long s, long n)
291 {
292 	Prog *p;
293 	uchar *cast;
294 	long l, fl, j;
295 	vlong o;
296 	int i, c;
297 
298 	memset(buf.dbuf, 0, n+Dbufslop);
299 	for(p = datap; p != P; p = p->link) {
300 		curp = p;
301 		l = p->from.sym->value + p->from.offset - s;
302 		c = p->from.scale;
303 		i = 0;
304 		if(l < 0) {
305 			if(l+c <= 0)
306 				continue;
307 			while(l < 0) {
308 				l++;
309 				i++;
310 			}
311 		}
312 		if(l >= n)
313 			continue;
314 		if(p->as != AINIT && p->as != ADYNT) {
315 			for(j=l+(c-i)-1; j>=l; j--)
316 				if(buf.dbuf[j]) {
317 					print("%P\n", p);
318 					diag("multiple initialization");
319 					break;
320 				}
321 		}
322 		switch(p->to.type) {
323 		case D_FCONST:
324 			switch(c) {
325 			default:
326 			case 4:
327 				fl = ieeedtof(&p->to.ieee);
328 				cast = (uchar*)&fl;
329 				if(debug['a'] && i == 0) {
330 					Bprint(&bso, pcstr, l+s+INITDAT);
331 					for(j=0; j<c; j++)
332 						Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
333 					Bprint(&bso, "\t%P\n", curp);
334 				}
335 				for(; i<c; i++) {
336 					buf.dbuf[l] = cast[fnuxi4[i]];
337 					l++;
338 				}
339 				break;
340 			case 8:
341 				cast = (uchar*)&p->to.ieee;
342 				if(debug['a'] && i == 0) {
343 					Bprint(&bso, pcstr, l+s+INITDAT);
344 					for(j=0; j<c; j++)
345 						Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
346 					Bprint(&bso, "\t%P\n", curp);
347 				}
348 				for(; i<c; i++) {
349 					buf.dbuf[l] = cast[fnuxi8[i]];
350 					l++;
351 				}
352 				break;
353 			}
354 			break;
355 
356 		case D_SCONST:
357 			if(debug['a'] && i == 0) {
358 				Bprint(&bso, pcstr, l+s+INITDAT);
359 				for(j=0; j<c; j++)
360 					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
361 				Bprint(&bso, "\t%P\n", curp);
362 			}
363 			for(; i<c; i++) {
364 				buf.dbuf[l] = p->to.scon[i];
365 				l++;
366 			}
367 			break;
368 		default:
369 			o = p->to.offset;
370 			if(p->to.type == D_ADDR) {
371 				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
372 					diag("DADDR type%P", p);
373 				if(p->to.sym) {
374 					if(p->to.sym->type == SUNDEF)
375 						ckoff(p->to.sym, o);
376 					o += p->to.sym->value;
377 					if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
378 						o += INITDAT;
379 					if(dlm)
380 						dynreloc(p->to.sym, l+s+INITDAT, 1);
381 				}
382 			}
383 			fl = o;
384 			cast = (uchar*)&fl;
385 			switch(c) {
386 			default:
387 				diag("bad nuxi %d %d\n%P", c, i, curp);
388 				break;
389 			case 1:
390 				if(debug['a'] && i == 0) {
391 					Bprint(&bso, pcstr, l+s+INITDAT);
392 					for(j=0; j<c; j++)
393 						Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
394 					Bprint(&bso, "\t%P\n", curp);
395 				}
396 				for(; i<c; i++) {
397 					buf.dbuf[l] = cast[inuxi1[i]];
398 					l++;
399 				}
400 				break;
401 			case 2:
402 				if(debug['a'] && i == 0) {
403 					Bprint(&bso, pcstr, l+s+INITDAT);
404 					for(j=0; j<c; j++)
405 						Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
406 					Bprint(&bso, "\t%P\n", curp);
407 				}
408 				for(; i<c; i++) {
409 					buf.dbuf[l] = cast[inuxi2[i]];
410 					l++;
411 				}
412 				break;
413 			case 4:
414 				if(debug['a'] && i == 0) {
415 					Bprint(&bso, pcstr, l+s+INITDAT);
416 					for(j=0; j<c; j++)
417 						Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
418 					Bprint(&bso, "\t%P\n", curp);
419 				}
420 				for(; i<c; i++) {
421 					buf.dbuf[l] = cast[inuxi4[i]];
422 					l++;
423 				}
424 				break;
425 			case 8:
426 				cast = (uchar*)&o;
427 				if(debug['a'] && i == 0) {
428 					Bprint(&bso, pcstr, l+s+INITDAT);
429 					for(j=0; j<c; j++)
430 						Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
431 					Bprint(&bso, "\t%P\n", curp);
432 				}
433 				for(; i<c; i++) {
434 					buf.dbuf[l] = cast[inuxi8[i]];
435 					l++;
436 				}
437 				break;
438 			}
439 			break;
440 		}
441 	}
442 	write(cout, buf.dbuf, n);
443 }
444 
445 vlong
446 rnd(vlong v, vlong r)
447 {
448 	vlong c;
449 
450 	if(r <= 0)
451 		return v;
452 	v += r - 1;
453 	c = v % r;
454 	if(c < 0)
455 		c += r;
456 	v -= c;
457 	return v;
458 }
459