xref: /plan9-contrib/sys/src/cmd/6l/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 && s->type != SLEAF)
18 		diag("entry not text: %s %d", s->name, s->type);
19 	return s->value;
20 }
21 
22 void
23 asmb(void)
24 {
25 	Prog *p;
26 	long v;
27 	ulong *op1;
28 
29 	if(debug['v'])
30 		Bprint(&bso, "%5.2f asmb\n", cputime());
31 	Bflush(&bso);
32 
33 	seek(cout, HEADR, 0);
34 	pc = INITTEXT;
35 	curp = firstp;
36 	for(p = firstp; p != P; p = p->link) {
37 		if(p->as == ATEXT) {
38 			curtext = p;
39 			autosize = p->to.offset + 4;
40 		}
41 		if(p->pc != pc) {
42 			if(!debug['a'])
43 				print("%P\n", curp);
44 			diag("phase error %lux sb %lux in %s\n", p->pc, pc, TNAME);
45 			pc = p->pc;
46 		}
47 		curp = p;
48 		asmins(p);
49 		if(cbc < sizeof(and))
50 			cflush();
51 		if(debug['a']) {
52 			Bprint(&bso, pcstr, pc);
53 			for(op1 = and; op1 < andptr; op1++)
54 				Bprint(&bso, " %.8ux", *op1);
55 			Bprint(&bso, "%.*s", (32+7-printcol)/8, "\t\t\t\t");
56 			Bprint(&bso, "%P\n", curp);
57 		}
58 		for(op1 = and; op1 < andptr; op1++) {
59 			v = *op1;
60 			cbp[0] = v;
61 			cbp[1] = v>>8;
62 			cbp[2] = v>>16;
63 			cbp[3] = v>>24;
64 			cbp += 4;
65 			pc += 4;
66 			cbc -= 4;
67 		}
68 	}
69 	cflush();
70 	switch(HEADTYPE) {
71 	default:
72 		diag("unknown header type %d\n", HEADTYPE);
73 	case 0:
74 		seek(cout, rnd(HEADR+textsize, 8192), 0);
75 		break;
76 	case 1:
77 		textsize = rnd(HEADR+textsize, 4096)-HEADR;
78 		seek(cout, textsize+HEADR, 0);
79 		break;
80 	case 2:
81 		seek(cout, HEADR+textsize, 0);
82 		break;
83 	case 3:
84 		seek(cout, HEADR+rnd(textsize, INITRND), 0);
85 		break;
86 	case 4:
87 		textsize = rnd(textsize, 4);
88 		seek(cout, textsize+HEADR, 0);
89 		break;
90 	}
91 
92 	if(debug['v'])
93 		Bprint(&bso, "%5.2f datblk\n", cputime());
94 	Bflush(&bso);
95 	for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
96 		if(datsize-v > sizeof(buf)-Dbufslop)
97 			datblk(v, sizeof(buf)-Dbufslop);
98 		else
99 			datblk(v, datsize-v);
100 	}
101 
102 	symsize = 0;
103 	lcsize = 0;
104 	if(!debug['s']) {
105 		if(debug['v'])
106 			Bprint(&bso, "%5.2f sym\n", cputime());
107 		Bflush(&bso);
108 		switch(HEADTYPE) {
109 		default:
110 		case 0:
111 			seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
112 			break;
113 		case 1:
114 			seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
115 			break;
116 		case 2:
117 			seek(cout, HEADR+textsize+datsize, 0);
118 			break;
119 		case 3:
120 			debug['s'] = 1;
121 			break;
122 		case 4:
123 			debug['s'] = 1;
124 			break;
125 		}
126 		if(!debug['s'])
127 			asmsym();
128 		if(debug['v'])
129 			Bprint(&bso, "%5.2f sp\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 	case 1:	/* unix coff */
163 	case 4:
164 		/*
165 		 * file header
166 		 */
167 		if(HEADTYPE == 4)
168 			lputl(0x00020161);	/* 2 sections, magic */
169 		else
170 			lputl(0x0002014c);	/* 2 sections, magic */
171 		lputl(0);			/* unix time stamp */
172 		lputl(0);			/* symbol table */
173 		lputl(0);			/* nsyms */
174 		lputl(0x00030020);		/* flags, sizeof a.out header */
175 		/*
176 		 * a.out header
177 		 */
178 		lputl(0x10b);			/* magic, version stamp */
179 		lputl(rnd(textsize, INITRND));	/* text sizes */
180 		lputl(datsize);			/* data sizes */
181 		lputl(bsssize);			/* bss sizes */
182 		lput(entryvalue());		/* va of entry */
183 		lputl(INITTEXT);		/* text start */
184 		lputl(INITDAT);			/* data start */
185 		lputl(0);			/* tag entries */
186 		/*
187 		 * text section header
188 		 */
189 		s8put(".text");
190 		lputl(INITTEXT);		/* pa */
191 		lputl(INITTEXT);		/* va */
192 		lputl(textsize);		/* text size */
193 		lputl(HEADR);			/* file offset */
194 		lputl(0);			/* relocation */
195 		lputl(0);			/* line numbers */
196 		lputl(0);			/* relocation, line numbers */
197 		lputl(0x20);			/* flags text only */
198 		lputl(0);			/* alignment */
199 		/*
200 		 * data section header
201 		 */
202 		s8put(".data");
203 		lputl(INITDAT);			/* pa */
204 		lputl(INITDAT);			/* va */
205 		lputl(datsize);			/* data size */
206 		lputl(HEADR+textsize);		/* file offset */
207 		lputl(0);			/* relocation */
208 		lputl(0);			/* line numbers */
209 		lputl(0);			/* relocation, line numbers */
210 		lputl(0x40);			/* flags data only */
211 		lputl(0);			/* alignment */
212 		break;
213 
214 	case 2:	/* plan9 */
215 		lput(4*12*12+7);		/* magic */
216 		lput(textsize);			/* sizes */
217 		lput(datsize);
218 		lput(bsssize);
219 		lput(symsize);			/* nsyms */
220 		lput(entryvalue());		/* va of entry */
221 		lput(0);			/* sp offsets */
222 		lput(lcsize);			/* line offsets */
223 		break;
224 	case 3:
225 		/* msdos boot */
226 		break;
227 	}
228 	cflush();
229 }
230 
231 void
232 lput(long l)
233 {
234 
235 	CPUT(l>>24)
236 	CPUT(l>>16)
237 	CPUT(l>>8)
238 	CPUT(l)
239 }
240 
241 void
242 lputl(long l)
243 {
244 
245 	CPUT(l)
246 	CPUT(l>>8)
247 	CPUT(l>>16)
248 	CPUT(l>>24)
249 }
250 
251 void
252 s8put(char *n)
253 {
254 	char name[8];
255 	int i;
256 
257 	strncpy(name, n, sizeof(name));
258 	for(i=0; i<sizeof(name); i++)
259 		CPUT(name[i])
260 }
261 
262 void
263 cflush(void)
264 {
265 	int n;
266 
267 	n = sizeof(buf.cbuf) - cbc;
268 	if(n)
269 		write(cout, buf.cbuf, n);
270 	cbp = buf.cbuf;
271 	cbc = sizeof(buf.cbuf);
272 }
273 
274 void
275 datblk(long s, long n)
276 {
277 	Prog *p;
278 	char *cast;
279 	long l, fl, j;
280 	int i, c;
281 
282 	memset(buf.dbuf, 0, n+Dbufslop);
283 	for(p = datap; p != P; p = p->link) {
284 		curp = p;
285 		l = p->from.sym->value + p->from.offset - s;
286 		c = p->from.scale;
287 		i = 0;
288 		if(l < 0) {
289 			if(l+c <= 0)
290 				continue;
291 			while(l < 0) {
292 				l++;
293 				i++;
294 			}
295 		}
296 		if(l >= n)
297 			continue;
298 		for(j=l+(c-i)-1; j>=l; j--)
299 			if(buf.dbuf[j]) {
300 				print("%P\n", p);
301 				diag("multiple initialization\n");
302 				break;
303 			}
304 		switch(p->to.type) {
305 		case D_FCONST:
306 			switch(c) {
307 			default:
308 			case 4:
309 				fl = ieeedtof(&p->to.ieee);
310 				cast = (char*)&fl;
311 				if(debug['a'] && i == 0) {
312 					Bprint(&bso, pcstr, l+s+INITDAT);
313 					for(j=0; j<c; j++)
314 						Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff);
315 					Bprint(&bso, "%.*s", (24+7-printcol)/8, "\t\t\t");
316 					Bprint(&bso, "%P\n", curp);
317 				}
318 				for(; i<c; i++) {
319 					buf.dbuf[l] = cast[fnuxi4[i]];
320 					l++;
321 				}
322 				break;
323 			case 8:
324 				cast = (char*)&p->to.ieee;
325 				if(debug['a'] && i == 0) {
326 					Bprint(&bso, pcstr, l+s+INITDAT);
327 					for(j=0; j<c; j++)
328 						Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
329 					Bprint(&bso, "%.*s", (24+7-printcol)/8, "\t\t\t");
330 					Bprint(&bso, "%P\n", curp);
331 				}
332 				for(; i<c; i++) {
333 					buf.dbuf[l] = cast[fnuxi8[i]];
334 					l++;
335 				}
336 				break;
337 			}
338 			break;
339 
340 		case D_SCONST:
341 			if(debug['a'] && i == 0) {
342 				Bprint(&bso, pcstr, l+s+INITDAT);
343 				for(j=0; j<c; j++)
344 					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
345 				Bprint(&bso, "%.*s", (24+7-printcol)/8, "\t\t\t");
346 				Bprint(&bso, "%P\n", curp);
347 			}
348 			for(; i<c; i++) {
349 				buf.dbuf[l] = p->to.scon[i];
350 				l++;
351 			}
352 			break;
353 		default:
354 			fl = p->to.offset;
355 			if(p->to.type == D_ADDR) {
356 				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
357 					diag("DADDR type%P\n", p);
358 				if(p->to.sym) {
359 					fl += p->to.sym->value;
360 					if(p->to.sym->type != STEXT && p->to.sym->type != SLEAF)
361 						fl += INITDAT;
362 				}
363 			}
364 			cast = (char*)&fl;
365 			switch(c) {
366 			default:
367 				diag("bad nuxi %d %d\n%P\n", c, i, curp);
368 				break;
369 			case 1:
370 				if(debug['a'] && i == 0) {
371 					Bprint(&bso, pcstr, l+s+INITDAT);
372 					for(j=0; j<c; j++)
373 						Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff);
374 					Bprint(&bso, "%.*s", (24+7-printcol)/8, "\t\t\t");
375 					Bprint(&bso, "%P\n", curp);
376 				}
377 				for(; i<c; i++) {
378 					buf.dbuf[l] = cast[inuxi1[i]];
379 					l++;
380 				}
381 				break;
382 			case 2:
383 				if(debug['a'] && i == 0) {
384 					Bprint(&bso, pcstr, l+s+INITDAT);
385 					for(j=0; j<c; j++)
386 						Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff);
387 					Bprint(&bso, "%.*s", (24+7-printcol)/8, "\t\t\t");
388 					Bprint(&bso, "%P\n", curp);
389 				}
390 				for(; i<c; i++) {
391 					buf.dbuf[l] = cast[inuxi2[i]];
392 					l++;
393 				}
394 				break;
395 			case 4:
396 				if(debug['a'] && i == 0) {
397 					Bprint(&bso, pcstr, l+s+INITDAT);
398 					for(j=0; j<c; j++)
399 						Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff);
400 					Bprint(&bso, "%.*s", (24+7-printcol)/8, "\t\t\t");
401 					Bprint(&bso, "%P\n", curp);
402 				}
403 				for(; i<c; i++) {
404 					buf.dbuf[l] = cast[inuxi4[i]];
405 					l++;
406 				}
407 				break;
408 			}
409 			break;
410 		}
411 	}
412 	write(cout, buf.dbuf, n);
413 }
414 
415 long
416 rnd(long v, long r)
417 {
418 	long c;
419 
420 	if(r <= 0)
421 		return v;
422 	v += r - 1;
423 	c = v % r;
424 	if(c < 0)
425 		c += r;
426 	v -= c;
427 	return v;
428 }
429