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