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