Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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