xref: /plan9-contrib/sys/src/cmd/6l/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 	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, " %.8lux", *op1);
55 			Bprint(&bso, "\t%P\n", curp);
56 		}
57 		for(op1 = and; op1 < andptr; op1++) {
58 			v = *op1;
59 			cbp[0] = v;
60 			cbp[1] = v>>8;
61 			cbp[2] = v>>16;
62 			cbp[3] = v>>24;
63 			cbp += 4;
64 			pc += 4;
65 			cbc -= 4;
66 		}
67 	}
68 	cflush();
69 	switch(HEADTYPE) {
70 	default:
71 		diag("unknown header type %d\n", HEADTYPE);
72 	case 0:
73 		seek(cout, rnd(HEADR+textsize, 8192), 0);
74 		break;
75 	case 1:
76 		textsize = rnd(HEADR+textsize, 4096)-HEADR;
77 		seek(cout, textsize+HEADR, 0);
78 		break;
79 	case 2:
80 		seek(cout, HEADR+textsize, 0);
81 		break;
82 	case 3:
83 		seek(cout, HEADR+rnd(textsize, INITRND), 0);
84 		break;
85 	case 4:
86 		textsize = rnd(textsize, 4);
87 		seek(cout, textsize+HEADR, 0);
88 		break;
89 	}
90 
91 	if(debug['v'])
92 		Bprint(&bso, "%5.2f datblk\n", cputime());
93 	Bflush(&bso);
94 	for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
95 		if(datsize-v > sizeof(buf)-Dbufslop)
96 			datblk(v, sizeof(buf)-Dbufslop);
97 		else
98 			datblk(v, datsize-v);
99 	}
100 
101 	symsize = 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 			debug['s'] = 1;
120 			break;
121 		case 4:
122 			debug['s'] = 1;
123 			break;
124 		}
125 		if(!debug['s'])
126 			asmsym();
127 		if(debug['v'])
128 			Bprint(&bso, "%5.2f sp\n", cputime());
129 		Bflush(&bso);
130 		if(!debug['s'])
131 			asmlc();
132 		cflush();
133 	}
134 	if(debug['v'])
135 		Bprint(&bso, "%5.2f headr\n", cputime());
136 	Bflush(&bso);
137 	seek(cout, 0L, 0);
138 	switch(HEADTYPE) {
139 	default:
140 	case 0:	/* garbage */
141 		lput(0x160L<<16);		/* magic and sections */
142 		lput(0L);			/* time and date */
143 		lput(rnd(HEADR+textsize, 4096)+datsize);
144 		lput(symsize);			/* nsyms */
145 		lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
146 		lput((0413<<16)|0437L);		/* magic and version */
147 		lput(rnd(HEADR+textsize, 4096));	/* sizes */
148 		lput(datsize);
149 		lput(bsssize);
150 		lput(entryvalue());		/* va of entry */
151 		lput(INITTEXT-HEADR);		/* va of base of text */
152 		lput(INITDAT);			/* va of base of data */
153 		lput(INITDAT+datsize);		/* va of base of bss */
154 		lput(~0L);			/* gp reg mask */
155 		lput(0L);
156 		lput(0L);
157 		lput(0L);
158 		lput(0L);
159 		lput(~0L);			/* gp value ?? */
160 		break;
161 	case 1:	/* unix coff */
162 	case 4:
163 		/*
164 		 * file header
165 		 */
166 		if(HEADTYPE == 4)
167 			lputl(0x00020161);	/* 2 sections, magic */
168 		else
169 			lputl(0x0002014c);	/* 2 sections, magic */
170 		lputl(0);			/* unix time stamp */
171 		lputl(0);			/* symbol table */
172 		lputl(0);			/* nsyms */
173 		lputl(0x00030020);		/* flags, sizeof a.out header */
174 		/*
175 		 * a.out header
176 		 */
177 		lputl(0x10b);			/* magic, version stamp */
178 		lputl(rnd(textsize, INITRND));	/* text sizes */
179 		lputl(datsize);			/* data sizes */
180 		lputl(bsssize);			/* bss sizes */
181 		lput(entryvalue());		/* va of entry */
182 		lputl(INITTEXT);		/* text start */
183 		lputl(INITDAT);			/* data start */
184 		lputl(0);			/* tag entries */
185 		/*
186 		 * text section header
187 		 */
188 		s8put(".text");
189 		lputl(INITTEXT);		/* pa */
190 		lputl(INITTEXT);		/* va */
191 		lputl(textsize);		/* text size */
192 		lputl(HEADR);			/* file offset */
193 		lputl(0);			/* relocation */
194 		lputl(0);			/* line numbers */
195 		lputl(0);			/* relocation, line numbers */
196 		lputl(0x20);			/* flags text only */
197 		lputl(0);			/* alignment */
198 		/*
199 		 * data section header
200 		 */
201 		s8put(".data");
202 		lputl(INITDAT);			/* pa */
203 		lputl(INITDAT);			/* va */
204 		lputl(datsize);			/* data size */
205 		lputl(HEADR+textsize);		/* file offset */
206 		lputl(0);			/* relocation */
207 		lputl(0);			/* line numbers */
208 		lputl(0);			/* relocation, line numbers */
209 		lputl(0x40);			/* flags data only */
210 		lputl(0);			/* alignment */
211 		break;
212 
213 	case 2:	/* plan9 */
214 		lput(4*12*12+7);		/* magic */
215 		lput(textsize);			/* sizes */
216 		lput(datsize);
217 		lput(bsssize);
218 		lput(symsize);			/* nsyms */
219 		lput(entryvalue());		/* va of entry */
220 		lput(0);			/* sp offsets */
221 		lput(lcsize);			/* line offsets */
222 		break;
223 	case 3:
224 		/* msdos boot */
225 		break;
226 	}
227 	cflush();
228 }
229 
230 void
231 lput(long l)
232 {
233 
234 	CPUT(l>>24)
235 	CPUT(l>>16)
236 	CPUT(l>>8)
237 	CPUT(l)
238 }
239 
240 void
241 lputl(long l)
242 {
243 
244 	CPUT(l)
245 	CPUT(l>>8)
246 	CPUT(l>>16)
247 	CPUT(l>>24)
248 }
249 
250 void
251 s8put(char *n)
252 {
253 	char name[8];
254 	int i;
255 
256 	strncpy(name, n, sizeof(name));
257 	for(i=0; i<sizeof(name); i++)
258 		CPUT(name[i])
259 }
260 
261 void
262 cflush(void)
263 {
264 	int n;
265 
266 	n = sizeof(buf.cbuf) - cbc;
267 	if(n)
268 		write(cout, buf.cbuf, n);
269 	cbp = buf.cbuf;
270 	cbc = sizeof(buf.cbuf);
271 }
272 
273 void
274 datblk(long s, long n)
275 {
276 	Prog *p;
277 	char *cast;
278 	long l, fl, j;
279 	int i, c;
280 
281 	memset(buf.dbuf, 0, n+Dbufslop);
282 	for(p = datap; p != P; p = p->link) {
283 		curp = p;
284 		l = p->from.sym->value + p->from.offset - s;
285 		c = p->from.scale;
286 		i = 0;
287 		if(l < 0) {
288 			if(l+c <= 0)
289 				continue;
290 			while(l < 0) {
291 				l++;
292 				i++;
293 			}
294 		}
295 		if(l >= n)
296 			continue;
297 		for(j=l+(c-i)-1; j>=l; j--)
298 			if(buf.dbuf[j]) {
299 				print("%P\n", p);
300 				diag("multiple initialization\n");
301 				break;
302 			}
303 		switch(p->to.type) {
304 		case D_FCONST:
305 			switch(c) {
306 			default:
307 			case 4:
308 				fl = ieeedtof(&p->to.ieee);
309 				cast = (char*)&fl;
310 				if(debug['a'] && i == 0) {
311 					Bprint(&bso, pcstr, l+s+INITDAT);
312 					for(j=0; j<c; j++)
313 						Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff);
314 					Bprint(&bso, "\t%P\n", curp);
315 				}
316 				for(; i<c; i++) {
317 					buf.dbuf[l] = cast[fnuxi4[i]];
318 					l++;
319 				}
320 				break;
321 			case 8:
322 				cast = (char*)&p->to.ieee;
323 				if(debug['a'] && i == 0) {
324 					Bprint(&bso, pcstr, l+s+INITDAT);
325 					for(j=0; j<c; j++)
326 						Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
327 					Bprint(&bso, "\t%P\n", curp);
328 				}
329 				for(; i<c; i++) {
330 					buf.dbuf[l] = cast[fnuxi8[i]];
331 					l++;
332 				}
333 				break;
334 			}
335 			break;
336 
337 		case D_SCONST:
338 			if(debug['a'] && i == 0) {
339 				Bprint(&bso, pcstr, l+s+INITDAT);
340 				for(j=0; j<c; j++)
341 					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
342 				Bprint(&bso, "\t%P\n", curp);
343 			}
344 			for(; i<c; i++) {
345 				buf.dbuf[l] = p->to.scon[i];
346 				l++;
347 			}
348 			break;
349 		default:
350 			fl = p->to.offset;
351 			if(p->to.type == D_ADDR) {
352 				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
353 					diag("DADDR type%P\n", p);
354 				if(p->to.sym) {
355 					fl += p->to.sym->value;
356 					if(p->to.sym->type != STEXT && p->to.sym->type != SLEAF)
357 						fl += INITDAT;
358 				}
359 			}
360 			cast = (char*)&fl;
361 			switch(c) {
362 			default:
363 				diag("bad nuxi %d %d\n%P\n", c, i, curp);
364 				break;
365 			case 1:
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[inuxi1[j]] & 0xff);
370 					Bprint(&bso, "\t%P\n", curp);
371 				}
372 				for(; i<c; i++) {
373 					buf.dbuf[l] = cast[inuxi1[i]];
374 					l++;
375 				}
376 				break;
377 			case 2:
378 				if(debug['a'] && i == 0) {
379 					Bprint(&bso, pcstr, l+s+INITDAT);
380 					for(j=0; j<c; j++)
381 						Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff);
382 					Bprint(&bso, "\t%P\n", curp);
383 				}
384 				for(; i<c; i++) {
385 					buf.dbuf[l] = cast[inuxi2[i]];
386 					l++;
387 				}
388 				break;
389 			case 4:
390 				if(debug['a'] && i == 0) {
391 					Bprint(&bso, pcstr, l+s+INITDAT);
392 					for(j=0; j<c; j++)
393 						Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff);
394 					Bprint(&bso, "\t%P\n", curp);
395 				}
396 				for(; i<c; i++) {
397 					buf.dbuf[l] = cast[inuxi4[i]];
398 					l++;
399 				}
400 				break;
401 			}
402 			break;
403 		}
404 	}
405 	write(cout, buf.dbuf, n);
406 }
407 
408 long
409 rnd(long v, long r)
410 {
411 	long c;
412 
413 	if(r <= 0)
414 		return v;
415 	v += r - 1;
416 	c = v % r;
417 	if(c < 0)
418 		c += r;
419 	v -= c;
420 	return v;
421 }
422