xref: /inferno-os/utils/6l/asm.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
1 #include	"l.h"
2 
3 #define	Dbufslop	100
4 
5 #define PADDR(a)	((ulong)(a) & ~0x80000000)
6 
7 long
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 lputl(long l)
56 {
57 	cput(l);
58 	cput(l>>8);
59 	cput(l>>16);
60 	cput(l>>24);
61 }
62 
63 void
64 strnput(char *s, int n)
65 {
66 	for(; *s && n > 0; s++){
67 		cput(*s);
68 		n--;
69 	}
70 	while(n > 0){
71 		cput(0);
72 		n--;
73 	}
74 }
75 
76 void
77 asmb(void)
78 {
79 	Prog *p;
80 	long v, magic;
81 	int a;
82 	uchar *op1;
83 
84 	if(debug['v'])
85 		Bprint(&bso, "%5.2f asmb\n", cputime());
86 	Bflush(&bso);
87 
88 	seek(cout, HEADR, 0);
89 	pc = INITTEXT;
90 	curp = firstp;
91 	for(p = firstp; p != P; p = p->link) {
92 		if(p->as == ATEXT)
93 			curtext = p;
94 		if(p->pc != pc) {
95 			if(!debug['a'])
96 				print("%P\n", curp);
97 			diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
98 			pc = p->pc;
99 		}
100 		curp = p;
101 		asmins(p);
102 		a = (andptr - and);
103 		if(cbc < a)
104 			cflush();
105 		if(debug['a']) {
106 			Bprint(&bso, pcstr, pc);
107 			for(op1 = and; op1 < andptr; op1++)
108 				Bprint(&bso, "%.2ux", *op1 & 0xff);
109 			Bprint(&bso, "\t%P\n", curp);
110 		}
111 		if(dlm) {
112 			if(p->as == ATEXT)
113 				reloca = nil;
114 			else if(reloca != nil)
115 				diag("reloc failure: %P", curp);
116 		}
117 		memmove(cbp, and, a);
118 		cbp += a;
119 		pc += a;
120 		cbc -= a;
121 	}
122 	cflush();
123 	switch(HEADTYPE) {
124 	default:
125 		diag("unknown header type %ld", HEADTYPE);
126 	case 0:
127 		seek(cout, rnd(HEADR+textsize, 8192), 0);
128 		break;
129 	case 1:
130 		textsize = rnd(HEADR+textsize, 4096)-HEADR;
131 		seek(cout, textsize+HEADR, 0);
132 		break;
133 	case 2:
134 	case 5:
135 		seek(cout, HEADR+textsize, 0);
136 		break;
137 	case 3:
138 	case 4:
139 		seek(cout, HEADR+rnd(textsize, INITRND), 0);
140 		break;
141 	}
142 
143 	if(debug['v'])
144 		Bprint(&bso, "%5.2f datblk\n", cputime());
145 	Bflush(&bso);
146 
147 	if(dlm){
148 		char buf[8];
149 
150 		write(cout, buf, INITDAT-textsize);
151 		textsize = INITDAT;
152 	}
153 
154 	for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
155 		if(datsize-v > sizeof(buf)-Dbufslop)
156 			datblk(v, sizeof(buf)-Dbufslop);
157 		else
158 			datblk(v, datsize-v);
159 	}
160 
161 	symsize = 0;
162 	spsize = 0;
163 	lcsize = 0;
164 	if(!debug['s']) {
165 		if(debug['v'])
166 			Bprint(&bso, "%5.2f sym\n", cputime());
167 		Bflush(&bso);
168 		switch(HEADTYPE) {
169 		default:
170 		case 0:
171 			seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
172 			break;
173 		case 1:
174 			seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
175 			break;
176 		case 2:
177 		case 5:
178 			seek(cout, HEADR+textsize+datsize, 0);
179 			break;
180 		case 3:
181 		case 4:
182 			debug['s'] = 1;
183 			break;
184 		}
185 		if(!debug['s'])
186 			asmsym();
187 		if(debug['v'])
188 			Bprint(&bso, "%5.2f sp\n", cputime());
189 		Bflush(&bso);
190 		if(debug['v'])
191 			Bprint(&bso, "%5.2f pc\n", cputime());
192 		Bflush(&bso);
193 		if(!debug['s'])
194 			asmlc();
195 		if(dlm)
196 			asmdyn();
197 		cflush();
198 	}
199 	else if(dlm){
200 		seek(cout, HEADR+textsize+datsize, 0);
201 		asmdyn();
202 		cflush();
203 	}
204 	if(debug['v'])
205 		Bprint(&bso, "%5.2f headr\n", cputime());
206 	Bflush(&bso);
207 	seek(cout, 0L, 0);
208 	switch(HEADTYPE) {
209 	default:
210 	case 0:	/* garbage */
211 		lput(0x160L<<16);		/* magic and sections */
212 		lput(0L);			/* time and date */
213 		lput(rnd(HEADR+textsize, 4096)+datsize);
214 		lput(symsize);			/* nsyms */
215 		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
216 		lput((0413<<16)|0437L);		/* magic and version */
217 		lput(rnd(HEADR+textsize, 4096));	/* sizes */
218 		lput(datsize);
219 		lput(bsssize);
220 		lput(entryvalue());		/* va of entry */
221 		lput(INITTEXT-HEADR);		/* va of base of text */
222 		lput(INITDAT);			/* va of base of data */
223 		lput(INITDAT+datsize);		/* va of base of bss */
224 		lput(~0L);			/* gp reg mask */
225 		lput(0L);
226 		lput(0L);
227 		lput(0L);
228 		lput(0L);
229 		lput(~0L);			/* gp value ?? */
230 		break;
231 		lputl(0);			/* x */
232 	case 1:	/* unix coff */
233 		/*
234 		 * file header
235 		 */
236 		lputl(0x0004014c);		/* 4 sections, magic */
237 		lputl(0);			/* unix time stamp */
238 		lputl(0);			/* symbol table */
239 		lputl(0);			/* nsyms */
240 		lputl(0x0003001c);		/* flags, sizeof a.out header */
241 		/*
242 		 * a.out header
243 		 */
244 		lputl(0x10b);			/* magic, version stamp */
245 		lputl(rnd(textsize, INITRND));	/* text sizes */
246 		lputl(datsize);			/* data sizes */
247 		lputl(bsssize);			/* bss sizes */
248 		lput(entryvalue());		/* va of entry */
249 		lputl(INITTEXT);		/* text start */
250 		lputl(INITDAT);			/* data start */
251 		/*
252 		 * text section header
253 		 */
254 		strnput(".text", 8);
255 		lputl(HEADR);			/* pa */
256 		lputl(HEADR);			/* va */
257 		lputl(textsize);		/* text size */
258 		lputl(HEADR);			/* file offset */
259 		lputl(0);			/* relocation */
260 		lputl(0);			/* line numbers */
261 		lputl(0);			/* relocation, line numbers */
262 		lputl(0x20);			/* flags text only */
263 		/*
264 		 * data section header
265 		 */
266 		strnput(".data", 8);
267 		lputl(INITDAT);			/* pa */
268 		lputl(INITDAT);			/* va */
269 		lputl(datsize);			/* data size */
270 		lputl(HEADR+textsize);		/* file offset */
271 		lputl(0);			/* relocation */
272 		lputl(0);			/* line numbers */
273 		lputl(0);			/* relocation, line numbers */
274 		lputl(0x40);			/* flags data only */
275 		/*
276 		 * bss section header
277 		 */
278 		strnput(".bss", 8);
279 		lputl(INITDAT+datsize);		/* pa */
280 		lputl(INITDAT+datsize);		/* va */
281 		lputl(bsssize);			/* bss size */
282 		lputl(0);			/* file offset */
283 		lputl(0);			/* relocation */
284 		lputl(0);			/* line numbers */
285 		lputl(0);			/* relocation, line numbers */
286 		lputl(0x80);			/* flags bss only */
287 		/*
288 		 * comment section header
289 		 */
290 		strnput(".comment", 8);
291 		lputl(0);			/* pa */
292 		lputl(0);			/* va */
293 		lputl(symsize+lcsize);		/* comment size */
294 		lputl(HEADR+textsize+datsize);	/* file offset */
295 		lputl(HEADR+textsize+datsize);	/* offset of syms */
296 		lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */
297 		lputl(0);			/* relocation, line numbers */
298 		lputl(0x200);			/* flags comment only */
299 		break;
300 	case 2:	/* plan9 */
301 		magic = 4*26*26+7;
302 		if(dlm)
303 			magic |= 0x80000000;
304 		lput(magic);			/* magic */
305 		lput(textsize);			/* sizes */
306 		lput(datsize);
307 		lput(bsssize);
308 		lput(symsize);			/* nsyms */
309 		lput(entryvalue());		/* va of entry */
310 		lput(spsize);			/* sp offsets */
311 		lput(lcsize);			/* line offsets */
312 		break;
313 	case 3:
314 		/* MS-DOS .COM */
315 		break;
316 	case 4:
317 		/* fake MS-DOS .EXE */
318 		v = rnd(HEADR+textsize, INITRND)+datsize;
319 		wputl(0x5A4D);			/* 'MZ' */
320 		wputl(v % 512);			/* bytes in last page */
321 		wputl(rnd(v, 512)/512);		/* total number of pages */
322 		wputl(0x0000);			/* number of reloc items */
323 		v = rnd(HEADR-(INITTEXT & 0xFFFF), 16);
324 		wputl(v/16);			/* size of header */
325 		wputl(0x0000);			/* minimum allocation */
326 		wputl(0xFFFF);			/* maximum allocation */
327 		wputl(0x0000);			/* initial ss value */
328 		wputl(0x0100);			/* initial sp value */
329 		wputl(0x0000);			/* complemented checksum */
330 		v = entryvalue();
331 		wputl(v);			/* initial ip value (!) */
332 		wputl(0x0000);			/* initial cs value */
333 		wputl(0x0000);
334 		wputl(0x0000);
335 		wputl(0x003E);			/* reloc table offset */
336 		wputl(0x0000);			/* overlay number */
337 		break;
338 	case 5:
339 		strnput("\177ELF", 4);		/* e_ident */
340 		cput(1);			/* class = 32 bit */
341 		cput(1);			/* data = LSB */
342 		cput(1);			/* version = CURRENT */
343 		strnput("", 9);
344 		wputl(2);			/* type = EXEC */
345 		wputl(3);			/* machine = 386 */
346 		lputl(1L);			/* version = CURRENT */
347 		lputl(PADDR(entryvalue()));	/* entry vaddr */
348 		lputl(52L);			/* offset to first phdr */
349 		lputl(0L);			/* offset to first shdr */
350 		lputl(0L);			/* flags = 386 */
351 		wputl(52);			/* Ehdr size */
352 		wputl(32);			/* Phdr size */
353 		wputl(3);			/* # of Phdrs */
354 		wputl(0);			/* Shdr size */
355 		wputl(0);			/* # of Shdrs */
356 		wputl(0);			/* Shdr string size */
357 
358 		lputl(1L);			/* text - type = PT_LOAD */
359 		lputl(HEADR);			/* file offset */
360 		lputl(INITTEXT);		/* vaddr */
361 		lputl(PADDR(INITTEXT));		/* paddr */
362 		lputl(textsize);		/* file size */
363 		lputl(textsize);		/* memory size */
364 		lputl(0x05L);			/* protections = RX */
365 		lputl(INITRND);			/* alignment */
366 
367 		lputl(1L);			/* data - type = PT_LOAD */
368 		lputl(HEADR+textsize);		/* file offset */
369 		lputl(INITDAT);			/* vaddr */
370 		lputl(PADDR(INITDAT));		/* paddr */
371 		lputl(datsize);			/* file size */
372 		lputl(datsize+bsssize);		/* memory size */
373 		lputl(0x06L);			/* protections = RW */
374 		lputl(INITRND);			/* alignment */
375 
376 		lputl(0L);			/* data - type = PT_NULL */
377 		lputl(HEADR+textsize+datsize);	/* file offset */
378 		lputl(0L);
379 		lputl(0L);
380 		lputl(symsize);			/* symbol table size */
381 		lputl(lcsize);			/* line number size */
382 		lputl(0x04L);			/* protections = R */
383 		lputl(0x04L);			/* alignment */
384 		break;
385 	}
386 	cflush();
387 }
388 
389 void
390 cflush(void)
391 {
392 	int n;
393 
394 	n = sizeof(buf.cbuf) - cbc;
395 	if(n)
396 		write(cout, buf.cbuf, n);
397 	cbp = buf.cbuf;
398 	cbc = sizeof(buf.cbuf);
399 }
400 
401 void
402 datblk(long s, long n)
403 {
404 	Prog *p;
405 	uchar *cast;
406 	long l, fl, j;
407 	vlong o;
408 	int i, c;
409 
410 	memset(buf.dbuf, 0, n+Dbufslop);
411 	for(p = datap; p != P; p = p->link) {
412 		curp = p;
413 		l = p->from.sym->value + p->from.offset - s;
414 		c = p->from.scale;
415 		i = 0;
416 		if(l < 0) {
417 			if(l+c <= 0)
418 				continue;
419 			while(l < 0) {
420 				l++;
421 				i++;
422 			}
423 		}
424 		if(l >= n)
425 			continue;
426 		if(p->as != AINIT && p->as != ADYNT) {
427 			for(j=l+(c-i)-1; j>=l; j--)
428 				if(buf.dbuf[j]) {
429 					print("%P\n", p);
430 					diag("multiple initialization");
431 					break;
432 				}
433 		}
434 		switch(p->to.type) {
435 		case D_FCONST:
436 			switch(c) {
437 			default:
438 			case 4:
439 				fl = ieeedtof(&p->to.ieee);
440 				cast = (uchar*)&fl;
441 				if(debug['a'] && i == 0) {
442 					Bprint(&bso, pcstr, l+s+INITDAT);
443 					for(j=0; j<c; j++)
444 						Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
445 					Bprint(&bso, "\t%P\n", curp);
446 				}
447 				for(; i<c; i++) {
448 					buf.dbuf[l] = cast[fnuxi4[i]];
449 					l++;
450 				}
451 				break;
452 			case 8:
453 				cast = (uchar*)&p->to.ieee;
454 				if(debug['a'] && i == 0) {
455 					Bprint(&bso, pcstr, l+s+INITDAT);
456 					for(j=0; j<c; j++)
457 						Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
458 					Bprint(&bso, "\t%P\n", curp);
459 				}
460 				for(; i<c; i++) {
461 					buf.dbuf[l] = cast[fnuxi8[i]];
462 					l++;
463 				}
464 				break;
465 			}
466 			break;
467 
468 		case D_SCONST:
469 			if(debug['a'] && i == 0) {
470 				Bprint(&bso, pcstr, l+s+INITDAT);
471 				for(j=0; j<c; j++)
472 					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
473 				Bprint(&bso, "\t%P\n", curp);
474 			}
475 			for(; i<c; i++) {
476 				buf.dbuf[l] = p->to.scon[i];
477 				l++;
478 			}
479 			break;
480 		default:
481 			o = p->to.offset;
482 			if(p->to.type == D_ADDR) {
483 				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
484 					diag("DADDR type%P", p);
485 				if(p->to.sym) {
486 					if(p->to.sym->type == SUNDEF)
487 						ckoff(p->to.sym, o);
488 					o += p->to.sym->value;
489 					if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
490 						o += INITDAT;
491 					if(dlm)
492 						dynreloc(p->to.sym, l+s+INITDAT, 1);
493 				}
494 			}
495 			fl = o;
496 			cast = (uchar*)&fl;
497 			switch(c) {
498 			default:
499 				diag("bad nuxi %d %d\n%P", c, i, curp);
500 				break;
501 			case 1:
502 				if(debug['a'] && i == 0) {
503 					Bprint(&bso, pcstr, l+s+INITDAT);
504 					for(j=0; j<c; j++)
505 						Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
506 					Bprint(&bso, "\t%P\n", curp);
507 				}
508 				for(; i<c; i++) {
509 					buf.dbuf[l] = cast[inuxi1[i]];
510 					l++;
511 				}
512 				break;
513 			case 2:
514 				if(debug['a'] && i == 0) {
515 					Bprint(&bso, pcstr, l+s+INITDAT);
516 					for(j=0; j<c; j++)
517 						Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
518 					Bprint(&bso, "\t%P\n", curp);
519 				}
520 				for(; i<c; i++) {
521 					buf.dbuf[l] = cast[inuxi2[i]];
522 					l++;
523 				}
524 				break;
525 			case 4:
526 				if(debug['a'] && i == 0) {
527 					Bprint(&bso, pcstr, l+s+INITDAT);
528 					for(j=0; j<c; j++)
529 						Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
530 					Bprint(&bso, "\t%P\n", curp);
531 				}
532 				for(; i<c; i++) {
533 					buf.dbuf[l] = cast[inuxi4[i]];
534 					l++;
535 				}
536 				break;
537 			case 8:
538 				cast = (uchar*)&o;
539 				if(debug['a'] && i == 0) {
540 					Bprint(&bso, pcstr, l+s+INITDAT);
541 					for(j=0; j<c; j++)
542 						Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
543 					Bprint(&bso, "\t%P\n", curp);
544 				}
545 				for(; i<c; i++) {
546 					buf.dbuf[l] = cast[inuxi8[i]];
547 					l++;
548 				}
549 				break;
550 			}
551 			break;
552 		}
553 	}
554 	write(cout, buf.dbuf, n);
555 }
556 
557 long
558 rnd(long v, long r)
559 {
560 	long c;
561 
562 	if(r <= 0)
563 		return v;
564 	v += r - 1;
565 	c = v % r;
566 	if(c < 0)
567 		c += r;
568 	v -= c;
569 	return v;
570 }
571