xref: /inferno-os/utils/8l/asm.c (revision adad243147f6102c6e975f48951c05745d56b92d)
1 #include	"l.h"
2 
3 #define	Dbufslop	100
4 
5 #define PADDR(a)	((ulong)(a) & ~0xF0000000)
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 %lux sb %lux in %s", p->pc, pc, TNAME);
98 			pc = p->pc;
99 		}
100 		curp = p;
101 		asmins(p);
102 		if(cbc < sizeof(and))
103 			cflush();
104 		a = (andptr - and);
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 	case 1:	/* unix coff */
232 		/*
233 		 * file header
234 		 */
235 		lputl(0x0004014c);		/* 4 sections, magic */
236 		lputl(0);			/* unix time stamp */
237 		lputl(0);			/* symbol table */
238 		lputl(0);			/* nsyms */
239 		lputl(0x0003001c);		/* flags, sizeof a.out header */
240 		/*
241 		 * a.out header
242 		 */
243 		lputl(0x10b);			/* magic, version stamp */
244 		lputl(rnd(textsize, INITRND));	/* text sizes */
245 		lputl(datsize);			/* data sizes */
246 		lputl(bsssize);			/* bss sizes */
247 		lput(entryvalue());		/* va of entry */
248 		lputl(INITTEXT);		/* text start */
249 		lputl(INITDAT);			/* data start */
250 		/*
251 		 * text section header
252 		 */
253 		strnput(".text", 8);
254 		lputl(HEADR);			/* pa */
255 		lputl(HEADR);			/* va */
256 		lputl(textsize);		/* text size */
257 		lputl(HEADR);			/* file offset */
258 		lputl(0);			/* relocation */
259 		lputl(0);			/* line numbers */
260 		lputl(0);			/* relocation, line numbers */
261 		lputl(0x20);			/* flags text only */
262 		/*
263 		 * data section header
264 		 */
265 		strnput(".data", 8);
266 		lputl(INITDAT);			/* pa */
267 		lputl(INITDAT);			/* va */
268 		lputl(datsize);			/* data size */
269 		lputl(HEADR+textsize);		/* file offset */
270 		lputl(0);			/* relocation */
271 		lputl(0);			/* line numbers */
272 		lputl(0);			/* relocation, line numbers */
273 		lputl(0x40);			/* flags data only */
274 		/*
275 		 * bss section header
276 		 */
277 		strnput(".bss", 8);
278 		lputl(INITDAT+datsize);		/* pa */
279 		lputl(INITDAT+datsize);		/* va */
280 		lputl(bsssize);			/* bss size */
281 		lputl(0);			/* file offset */
282 		lputl(0);			/* relocation */
283 		lputl(0);			/* line numbers */
284 		lputl(0);			/* relocation, line numbers */
285 		lputl(0x80);			/* flags bss only */
286 		/*
287 		 * comment section header
288 		 */
289 		strnput(".comment", 8);
290 		lputl(0);			/* pa */
291 		lputl(0);			/* va */
292 		lputl(symsize+lcsize);		/* comment size */
293 		lputl(HEADR+textsize+datsize);	/* file offset */
294 		lputl(HEADR+textsize+datsize);	/* offset of syms */
295 		lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */
296 		lputl(0);			/* relocation, line numbers */
297 		lputl(0x200);			/* flags comment only */
298 		break;
299 	case 2:	/* plan9 */
300 		magic = 4*11*11+7;
301 		if(dlm)
302 			magic |= 0x80000000;
303 		lput(magic);			/* magic */
304 		lput(textsize);			/* sizes */
305 		lput(datsize);
306 		lput(bsssize);
307 		lput(symsize);			/* nsyms */
308 		lput(entryvalue());		/* va of entry */
309 		lput(spsize);			/* sp offsets */
310 		lput(lcsize);			/* line offsets */
311 		break;
312 	case 3:
313 		/* MS-DOS .COM */
314 		break;
315 	case 4:
316 		/* fake MS-DOS .EXE */
317 		v = rnd(HEADR+textsize, INITRND)+datsize;
318 		wputl(0x5A4D);			/* 'MZ' */
319 		wputl(v % 512);			/* bytes in last page */
320 		wputl(rnd(v, 512)/512);		/* total number of pages */
321 		wputl(0x0000);			/* number of reloc items */
322 		v = rnd(HEADR-(INITTEXT & 0xFFFF), 16);
323 		wputl(v/16);			/* size of header */
324 		wputl(0x0000);			/* minimum allocation */
325 		wputl(0xFFFF);			/* maximum allocation */
326 		wputl(0x0000);			/* initial ss value */
327 		wputl(0x0100);			/* initial sp value */
328 		wputl(0x0000);			/* complemented checksum */
329 		v = entryvalue();
330 		wputl(v);			/* initial ip value (!) */
331 		wputl(0x0000);			/* initial cs value */
332 		wputl(0x0000);
333 		wputl(0x0000);
334 		wputl(0x003E);			/* reloc table offset */
335 		wputl(0x0000);			/* overlay number */
336 		break;
337 	case 5:
338 		strnput("\177ELF", 4);		/* e_ident */
339 		cput(1);			/* class = 32 bit */
340 		cput(1);			/* data = LSB */
341 		cput(1);			/* version = CURRENT */
342 		strnput("", 9);
343 		wputl(2);			/* type = EXEC */
344 		wputl(3);			/* machine = 386 */
345 		lputl(1L);			/* version = CURRENT */
346 		lputl(PADDR(entryvalue()));	/* entry vaddr */
347 		lputl(52L);			/* offset to first phdr */
348 		lputl(0L);			/* offset to first shdr */
349 		lputl(0L);			/* flags = 386 */
350 		wputl(52);			/* Ehdr size */
351 		wputl(32);			/* Phdr size */
352 		wputl(3);			/* # of Phdrs */
353 		wputl(0);			/* Shdr size */
354 		wputl(0);			/* # of Shdrs */
355 		wputl(0);			/* Shdr string size */
356 
357 		lputl(1L);			/* text - type = PT_LOAD */
358 		lputl(HEADR);			/* file offset */
359 		lputl(INITTEXT);		/* vaddr */
360 		lputl(PADDR(INITTEXT));		/* paddr */
361 		lputl(textsize);		/* file size */
362 		lputl(textsize);		/* memory size */
363 		lputl(0x05L);			/* protections = RX */
364 		lputl(INITRND);			/* alignment */
365 
366 		lputl(1L);			/* data - type = PT_LOAD */
367 		lputl(HEADR+textsize);		/* file offset */
368 		lputl(INITDAT);			/* vaddr */
369 		lputl(PADDR(INITDAT));		/* paddr */
370 		lputl(datsize);			/* file size */
371 		lputl(datsize+bsssize);		/* memory size */
372 		lputl(0x06L);			/* protections = RW */
373 		lputl(INITRND);			/* alignment */
374 
375 		lputl(0L);			/* data - type = PT_NULL */
376 		lputl(HEADR+textsize+datsize);	/* file offset */
377 		lputl(0L);
378 		lputl(0L);
379 		lputl(symsize);			/* symbol table size */
380 		lputl(lcsize);			/* line number size */
381 		lputl(0x04L);			/* protections = R */
382 		lputl(0x04L);			/* alignment */
383 		break;
384 	}
385 	cflush();
386 }
387 
388 void
389 cflush(void)
390 {
391 	int n;
392 
393 	n = sizeof(buf.cbuf) - cbc;
394 	if(n)
395 		write(cout, buf.cbuf, n);
396 	cbp = buf.cbuf;
397 	cbc = sizeof(buf.cbuf);
398 }
399 
400 void
401 datblk(long s, long n)
402 {
403 	Prog *p;
404 	char *cast;
405 	long l, fl, j;
406 	int i, c;
407 
408 	memset(buf.dbuf, 0, n+Dbufslop);
409 	for(p = datap; p != P; p = p->link) {
410 		curp = p;
411 		l = p->from.sym->value + p->from.offset - s;
412 		c = p->from.scale;
413 		i = 0;
414 		if(l < 0) {
415 			if(l+c <= 0)
416 				continue;
417 			while(l < 0) {
418 				l++;
419 				i++;
420 			}
421 		}
422 		if(l >= n)
423 			continue;
424 		if(p->as != AINIT && p->as != ADYNT) {
425 			for(j=l+(c-i)-1; j>=l; j--)
426 				if(buf.dbuf[j]) {
427 					print("%P\n", p);
428 					diag("multiple initialization");
429 					break;
430 				}
431 		}
432 		switch(p->to.type) {
433 		case D_FCONST:
434 			switch(c) {
435 			default:
436 			case 4:
437 				fl = ieeedtof(&p->to.ieee);
438 				cast = (char*)&fl;
439 				if(debug['a'] && i == 0) {
440 					Bprint(&bso, pcstr, l+s+INITDAT);
441 					for(j=0; j<c; j++)
442 						Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff);
443 					Bprint(&bso, "\t%P\n", curp);
444 				}
445 				for(; i<c; i++) {
446 					buf.dbuf[l] = cast[fnuxi4[i]];
447 					l++;
448 				}
449 				break;
450 			case 8:
451 				cast = (char*)&p->to.ieee;
452 				if(debug['a'] && i == 0) {
453 					Bprint(&bso, pcstr, l+s+INITDAT);
454 					for(j=0; j<c; j++)
455 						Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
456 					Bprint(&bso, "\t%P\n", curp);
457 				}
458 				for(; i<c; i++) {
459 					buf.dbuf[l] = cast[fnuxi8[i]];
460 					l++;
461 				}
462 				break;
463 			}
464 			break;
465 
466 		case D_SCONST:
467 			if(debug['a'] && i == 0) {
468 				Bprint(&bso, pcstr, l+s+INITDAT);
469 				for(j=0; j<c; j++)
470 					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
471 				Bprint(&bso, "\t%P\n", curp);
472 			}
473 			for(; i<c; i++) {
474 				buf.dbuf[l] = p->to.scon[i];
475 				l++;
476 			}
477 			break;
478 		default:
479 			fl = p->to.offset;
480 			if(p->to.type == D_ADDR) {
481 				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
482 					diag("DADDR type%P", p);
483 				if(p->to.sym) {
484 					if(p->to.sym->type == SUNDEF)
485 						ckoff(p->to.sym, fl);
486 					fl += p->to.sym->value;
487 					if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
488 						fl += INITDAT;
489 					if(dlm)
490 						dynreloc(p->to.sym, l+s+INITDAT, 1);
491 				}
492 			}
493 			cast = (char*)&fl;
494 			switch(c) {
495 			default:
496 				diag("bad nuxi %d %d\n%P", c, i, curp);
497 				break;
498 			case 1:
499 				if(debug['a'] && i == 0) {
500 					Bprint(&bso, pcstr, l+s+INITDAT);
501 					for(j=0; j<c; j++)
502 						Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff);
503 					Bprint(&bso, "\t%P\n", curp);
504 				}
505 				for(; i<c; i++) {
506 					buf.dbuf[l] = cast[inuxi1[i]];
507 					l++;
508 				}
509 				break;
510 			case 2:
511 				if(debug['a'] && i == 0) {
512 					Bprint(&bso, pcstr, l+s+INITDAT);
513 					for(j=0; j<c; j++)
514 						Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff);
515 					Bprint(&bso, "\t%P\n", curp);
516 				}
517 				for(; i<c; i++) {
518 					buf.dbuf[l] = cast[inuxi2[i]];
519 					l++;
520 				}
521 				break;
522 			case 4:
523 				if(debug['a'] && i == 0) {
524 					Bprint(&bso, pcstr, l+s+INITDAT);
525 					for(j=0; j<c; j++)
526 						Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff);
527 					Bprint(&bso, "\t%P\n", curp);
528 				}
529 				for(; i<c; i++) {
530 					buf.dbuf[l] = cast[inuxi4[i]];
531 					l++;
532 				}
533 				break;
534 			}
535 			break;
536 		}
537 	}
538 	write(cout, buf.dbuf, n);
539 }
540 
541 long
542 rnd(long v, long r)
543 {
544 	long c;
545 
546 	if(r <= 0)
547 		return v;
548 	v += r - 1;
549 	c = v % r;
550 	if(c < 0)
551 		c += r;
552 	v -= c;
553 	return v;
554 }
555