xref: /plan9-contrib/sys/src/cmd/ql/asm.c (revision a6a9e07217f318acf170f99684a55fba5200524f)
1 #include	"l.h"
2 
3 #define	LPUT(c)\
4 	{\
5 		cbp[0] = (c)>>24;\
6 		cbp[1] = (c)>>16;\
7 		cbp[2] = (c)>>8;\
8 		cbp[3] = (c);\
9 		cbp += 4;\
10 		cbc -= 4;\
11 		if(cbc <= 0)\
12 			cflush();\
13 	}
14 
15 #define	CPUT(c)\
16 	{\
17 		cbp[0] = (c);\
18 		cbp++;\
19 		cbc--;\
20 		if(cbc <= 0)\
21 			cflush();\
22 	}
23 
24 void	strnput(char*, int);
25 
26 long
27 entryvalue(void)
28 {
29 	char *a;
30 	Sym *s;
31 
32 	a = INITENTRY;
33 	if(*a >= '0' && *a <= '9')
34 		return atolwhex(a);
35 	s = lookup(a, 0);
36 	if(s->type == 0)
37 		return INITTEXT;
38 	if(s->type != STEXT && s->type != SLEAF)
39 		diag("entry not text: %s", s->name);
40 	return s->value;
41 }
42 
43 void
44 asmb(void)
45 {
46 	Prog *p;
47 	long t;
48 	Optab *o;
49 
50 	if(debug['v'])
51 		Bprint(&bso, "%5.2f asm\n", cputime());
52 	Bflush(&bso);
53 	seek(cout, HEADR, 0);
54 	pc = INITTEXT;
55 	for(p = firstp; p != P; p = p->link) {
56 		if(p->as == ATEXT) {
57 			curtext = p;
58 			autosize = p->to.offset + 4;
59 			if(p->from3.type == D_CONST) {
60 				for(; pc < p->pc; pc++)
61 					CPUT(0);
62 			}
63 		}
64 		if(p->pc != pc) {
65 			diag("phase error %lux sb %lux",
66 				p->pc, pc);
67 			if(!debug['a'])
68 				prasm(curp);
69 			pc = p->pc;
70 		}
71 		curp = p;
72 		o = oplook(p);	/* could probably avoid this call */
73 		if(asmout(p, o, 0)) {
74 			p = p->link;
75 			pc += 4;
76 		}
77 		pc += o->size;
78 	}
79 	if(debug['a'])
80 		Bprint(&bso, "\n");
81 	Bflush(&bso);
82 	cflush();
83 
84 	curtext = P;
85 	switch(HEADTYPE) {
86 	case 0:
87 	case 1:
88 	case 2:
89 		seek(cout, HEADR+textsize, 0);
90 		break;
91 	case 3:
92 		seek(cout, rnd(HEADR+textsize, 4), 0);
93 		break;
94 	case 4:
95 		seek(cout, rnd(HEADR+textsize, 4096), 0);
96 		break;
97 	}
98 	for(t = 0; t < datsize; t += sizeof(buf)-100) {
99 		if(datsize-t > sizeof(buf)-100)
100 			datblk(t, sizeof(buf)-100);
101 		else
102 			datblk(t, datsize-t);
103 	}
104 
105 	symsize = 0;
106 	lcsize = 0;
107 	if(!debug['s']) {
108 		if(debug['v'])
109 			Bprint(&bso, "%5.2f sym\n", cputime());
110 		Bflush(&bso);
111 		switch(HEADTYPE) {
112 		case 0:
113 			seek(cout, HEADR+textsize+datsize, 0);
114 			break;
115 		case 3:
116 			seek(cout, rnd(HEADR+textsize, 4)+datsize, 0);
117 			break;
118 		case 4:
119 			seek(cout, rnd(HEADR+textsize, 4096)+datsize, 0);
120 			break;
121 		}
122 		if(!debug['s'])
123 			asmsym();
124 		if(debug['v'])
125 			Bprint(&bso, "%5.2f sp\n", cputime());
126 		Bflush(&bso);
127 		if(!debug['s'])
128 			asmlc();
129 		if(HEADTYPE == 0 || HEADTYPE == 1)	/* round up file length for boot image */
130 			if((symsize+lcsize) & 1)
131 				CPUT(0);
132 		cflush();
133 	}
134 
135 	seek(cout, 0L, 0);
136 	switch(HEADTYPE) {
137 	case 0:
138 		lput(0x1030107);		/* magic and sections */
139 		lput(textsize);			/* sizes */
140 		lput(datsize);
141 		lput(bsssize);
142 		lput(symsize);			/* nsyms */
143 		lput(entryvalue());		/* va of entry */
144 		lput(0L);
145 		lput(lcsize);
146 		break;
147 	case 1:
148 		lput(0x4a6f7921);	/* Joy! */
149 		lput(0x70656666);	/* peff */
150 		lput(0x70777063);	/* pwpc */
151 		lput(1);
152 		lput(0);
153 		lput(0);
154 		lput(0);
155 		lput(0);
156 		lput(0x30002);	/*YY*/
157 		lput(0);
158 		lput(~0);
159 		lput(0);
160 		lput(textsize+datsize);
161 		lput(textsize+datsize);
162 		lput(textsize+datsize);
163 		lput(0xd0);	/* header size */
164 		lput(0x10400);
165 		lput(~0);
166 		lput(0);
167 		lput(0xc);
168 		lput(0xc);
169 		lput(0xc);
170 		lput(0xc0);
171 		lput(0x01010400);
172 		lput(~0);
173 		lput(0);
174 		lput(0x38);
175 		lput(0x38);
176 		lput(0x38);
177 		lput(0x80);
178 		lput(0x04040400);
179 		lput(0);
180 		lput(1);
181 		lput(0);
182 		lput(~0);
183 		lput(0);
184 		lput(~0);
185 		lput(0);
186 		lput(0);
187 		lput(0);
188 		lput(0);
189 		lput(0);
190 		lput(0);
191 		lput(0);
192 		lput(0);
193 		lput(0);
194 		lput(0);
195 		lput(0);
196 		lput(0x3100);	/* load address */
197 		lput(0);
198 		lput(0);
199 		lput(0);	/* whew! */
200 		break;
201 	case 2:
202 		lput(4*21*21+7);		/* magic */
203 		lput(textsize);			/* sizes */
204 		lput(datsize);
205 		lput(bsssize);
206 		lput(symsize);			/* nsyms */
207 		lput(entryvalue());		/* va of entry */
208 		lput(0L);
209 		lput(lcsize);
210 		break;
211 	case 3:
212 		break;
213 	case 4:
214 		lput((0x1DFL<<16)|3L);		/* magic and sections */
215 		lput(time(0));			/* time and date */
216 		lput(rnd(HEADR+textsize, 4096)+datsize);
217 		lput(symsize);			/* nsyms */
218 		lput((0x48L<<16)|15L);		/* size of optional hdr and flags */
219 
220 		lput((0413<<16)|01L);	/* magic and version */
221 		lput(textsize);			/* sizes */
222 		lput(datsize);
223 		lput(bsssize);
224 		lput(entryvalue());		/* va of entry */
225 		lput(INITTEXT);			/* va of base of text */
226 		lput(INITDAT);			/* va of base of data */
227 		lput(INITDAT);		/* address of TOC */
228 		lput((1L<<16)|1);			/* sn(entry) | sn(text) */
229 		lput((2L<<16)|1);		/* sn(data) | sn(toc) */
230 		lput((0L<<16)|3);		/* sn(loader) | sn(bss) */
231 		lput((3L<<16)|3);		/* maxalign(text) | maxalign(data) */
232 		lput(('1'<<24)|('L'<<16)|0);	/* type field, and reserved */
233 		lput(0);	/* max stack allowed */
234 		lput(0);	/* max data allowed */
235 		lput(0); lput(0); lput(0);	/* reserved */
236 
237 		strnput(".text", 8);		/* text segment */
238 		lput(INITTEXT);			/* address */
239 		lput(INITTEXT);
240 		lput(textsize);
241 		lput(HEADR);
242 		lput(0L);
243 		lput(HEADR+textsize+datsize+symsize);
244 		lput(lcsize);			/* line number size */
245 		lput(0x20L);			/* flags */
246 
247 		strnput(".data", 8);		/* data segment */
248 		lput(INITDAT);			/* address */
249 		lput(INITDAT);
250 		lput(datsize);
251 		lput(rnd(HEADR+textsize, 4096));	/* sizes */
252 		lput(0L);
253 		lput(0L);
254 		lput(0L);
255 		lput(0x40L);			/* flags */
256 
257 		strnput(".bss", 8);		/* bss segment */
258 		lput(INITDAT+datsize);		/* address */
259 		lput(INITDAT+datsize);
260 		lput(bsssize);
261 		lput(0L);
262 		lput(0L);
263 		lput(0L);
264 		lput(0L);
265 		lput(0x80L);			/* flags */
266 		break;
267 	}
268 	cflush();
269 }
270 
271 void
272 strnput(char *s, int n)
273 {
274 	for(; *s; s++){
275 		CPUT(*s);
276 		n--;
277 	}
278 	for(; n > 0; n--)
279 		CPUT(0);
280 }
281 
282 void
283 lput(long l)
284 {
285 
286 	LPUT(l);
287 }
288 
289 void
290 cflush(void)
291 {
292 	int n;
293 
294 	n = sizeof(buf.cbuf) - cbc;
295 	if(n)
296 		write(cout, buf.cbuf, n);
297 	cbp = buf.cbuf;
298 	cbc = sizeof(buf.cbuf);
299 }
300 
301 void
302 asmsym(void)
303 {
304 	Prog *p;
305 	Auto *a;
306 	Sym *s;
307 	int h;
308 
309 	s = lookup("etext", 0);
310 	if(s->type == STEXT)
311 		putsymb(s->name, 'T', s->value, s->version);
312 
313 	for(h=0; h<NHASH; h++)
314 		for(s=hash[h]; s!=S; s=s->link)
315 			switch(s->type) {
316 			case SCONST:
317 				putsymb(s->name, 'D', s->value, s->version);
318 				continue;
319 
320 			case SDATA:
321 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
322 				continue;
323 
324 			case SBSS:
325 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
326 				continue;
327 
328 			case SFILE:
329 				putsymb(s->name, 'f', s->value, s->version);
330 				continue;
331 			}
332 
333 	for(p=textp; p!=P; p=p->cond) {
334 		s = p->from.sym;
335 		if(s->type != STEXT && s->type != SLEAF)
336 			continue;
337 
338 		/* filenames first */
339 		for(a=p->to.autom; a; a=a->link)
340 			if(a->type == D_FILE)
341 				putsymb(a->sym->name, 'z', a->offset, 0);
342 			else
343 			if(a->type == D_FILE1)
344 				putsymb(a->sym->name, 'Z', a->offset, 0);
345 
346 		if(s->type == STEXT)
347 			putsymb(s->name, 'T', s->value, s->version);
348 		else
349 			putsymb(s->name, 'L', s->value, s->version);
350 
351 		/* frame, auto and param after */
352 		putsymb(".frame", 'm', p->to.offset+4, 0);
353 		for(a=p->to.autom; a; a=a->link)
354 			if(a->type == D_AUTO)
355 				putsymb(a->sym->name, 'a', -a->offset, 0);
356 			else
357 			if(a->type == D_PARAM)
358 				putsymb(a->sym->name, 'p', a->offset, 0);
359 	}
360 	if(debug['v'] || debug['n'])
361 		Bprint(&bso, "symsize = %lud\n", symsize);
362 	Bflush(&bso);
363 }
364 
365 void
366 putsymb(char *s, int t, long v, int ver)
367 {
368 	int i, f;
369 
370 	if(t == 'f')
371 		s++;
372 	LPUT(v);
373 	if(ver)
374 		t += 'a' - 'A';
375 	CPUT(t+0x80);			/* 0x80 is variable length */
376 
377 	if(t == 'Z' || t == 'z') {
378 		CPUT(s[0]);
379 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
380 			CPUT(s[i]);
381 			CPUT(s[i+1]);
382 		}
383 		CPUT(0);
384 		CPUT(0);
385 		i++;
386 	}
387 	else {
388 		for(i=0; s[i]; i++)
389 			CPUT(s[i]);
390 		CPUT(0);
391 	}
392 	symsize += 4 + 1 + i + 1;
393 
394 	if(debug['n']) {
395 		if(t == 'z' || t == 'Z') {
396 			Bprint(&bso, "%c %.8lux ", t, v);
397 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
398 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
399 				Bprint(&bso, "/%x", f);
400 			}
401 			Bprint(&bso, "\n");
402 			return;
403 		}
404 		if(ver)
405 			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
406 		else
407 			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
408 	}
409 }
410 
411 #define	MINLC	4
412 void
413 asmlc(void)
414 {
415 	long oldpc, oldlc;
416 	Prog *p;
417 	long v, s;
418 
419 	oldpc = INITTEXT;
420 	oldlc = 0;
421 	for(p = firstp; p != P; p = p->link) {
422 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
423 			if(p->as == ATEXT)
424 				curtext = p;
425 			if(debug['L'])
426 				Bprint(&bso, "%6lux %P\n",
427 					p->pc, p);
428 			continue;
429 		}
430 		if(debug['L'])
431 			Bprint(&bso, "\t\t%6ld", lcsize);
432 		v = (p->pc - oldpc) / MINLC;
433 		while(v) {
434 			s = 127;
435 			if(v < 127)
436 				s = v;
437 			CPUT(s+128);	/* 129-255 +pc */
438 			if(debug['L'])
439 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
440 			v -= s;
441 			lcsize++;
442 		}
443 		s = p->line - oldlc;
444 		oldlc = p->line;
445 		oldpc = p->pc + MINLC;
446 		if(s > 64 || s < -64) {
447 			CPUT(0);	/* 0 vv +lc */
448 			CPUT(s>>24);
449 			CPUT(s>>16);
450 			CPUT(s>>8);
451 			CPUT(s);
452 			if(debug['L']) {
453 				if(s > 0)
454 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
455 						s, 0, s);
456 				else
457 					Bprint(&bso, " lc%ld(%d,%ld)\n",
458 						s, 0, s);
459 				Bprint(&bso, "%6lux %P\n",
460 					p->pc, p);
461 			}
462 			lcsize += 5;
463 			continue;
464 		}
465 		if(s > 0) {
466 			CPUT(0+s);	/* 1-64 +lc */
467 			if(debug['L']) {
468 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
469 				Bprint(&bso, "%6lux %P\n",
470 					p->pc, p);
471 			}
472 		} else {
473 			CPUT(64-s);	/* 65-128 -lc */
474 			if(debug['L']) {
475 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
476 				Bprint(&bso, "%6lux %P\n",
477 					p->pc, p);
478 			}
479 		}
480 		lcsize++;
481 	}
482 	while(lcsize & 1) {
483 		s = 129;
484 		CPUT(s);
485 		lcsize++;
486 	}
487 	if(debug['v'] || debug['L'])
488 		Bprint(&bso, "lcsize = %ld\n", lcsize);
489 	Bflush(&bso);
490 }
491 
492 void
493 datblk(long s, long n)
494 {
495 	Prog *p;
496 	char *cast;
497 	long l, fl, j, d;
498 	int i, c;
499 
500 	memset(buf.dbuf, 0, n+100);
501 	for(p = datap; p != P; p = p->link) {
502 		curp = p;
503 		l = p->from.sym->value + p->from.offset - s;
504 		c = p->reg;
505 		i = 0;
506 		if(l < 0) {
507 			if(l+c <= 0)
508 				continue;
509 			while(l < 0) {
510 				l++;
511 				i++;
512 			}
513 		}
514 		if(l >= n)
515 			continue;
516 		if(p->as != AINIT && p->as != ADYNT) {
517 			for(j=l+(c-i)-1; j>=l; j--)
518 				if(buf.dbuf[j]) {
519 					print("%P\n", p);
520 					diag("multiple initialization");
521 					break;
522 				}
523 		}
524 		switch(p->to.type) {
525 		default:
526 			diag("unknown mode in initialization\n%P", p);
527 			break;
528 
529 		case D_FCONST:
530 			switch(c) {
531 			default:
532 			case 4:
533 				fl = ieeedtof(&p->to.ieee);
534 				cast = (char*)&fl;
535 				for(; i<c; i++) {
536 					buf.dbuf[l] = cast[fnuxi8[i+4]];
537 					l++;
538 				}
539 				break;
540 			case 8:
541 				cast = (char*)&p->to.ieee;
542 				for(; i<c; i++) {
543 					buf.dbuf[l] = cast[fnuxi8[i]];
544 					l++;
545 				}
546 				break;
547 			}
548 			break;
549 
550 		case D_SCONST:
551 			for(; i<c; i++) {
552 				buf.dbuf[l] = p->to.sval[i];
553 				l++;
554 			}
555 			break;
556 
557 		case D_CONST:
558 			d = p->to.offset;
559 			if(p->to.sym) {
560 				if(p->to.sym->type == STEXT ||
561 				   p->to.sym->type == SLEAF)
562 					d += p->to.sym->value;
563 				if(p->to.sym->type == SDATA)
564 					d += p->to.sym->value + INITDAT;
565 				if(p->to.sym->type == SBSS)
566 					d += p->to.sym->value + INITDAT;
567 			}
568 			cast = (char*)&d;
569 			switch(c) {
570 			default:
571 				diag("bad nuxi %d %d\n%P", c, i, curp);
572 				break;
573 			case 1:
574 				for(; i<c; i++) {
575 					buf.dbuf[l] = cast[inuxi1[i]];
576 					l++;
577 				}
578 				break;
579 			case 2:
580 				for(; i<c; i++) {
581 					buf.dbuf[l] = cast[inuxi2[i]];
582 					l++;
583 				}
584 				break;
585 			case 4:
586 				for(; i<c; i++) {
587 					buf.dbuf[l] = cast[inuxi4[i]];
588 					l++;
589 				}
590 				break;
591 			}
592 			break;
593 		}
594 	}
595 	write(cout, buf.dbuf, n);
596 }
597