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