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
entryvalue(void)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
elf32jmp(Putl putl)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
asmb(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
strnput(char * s,int n)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
cput(long l)354 cput(long l)
355 {
356 CPUT(l);
357 }
358
359 void
wput(long l)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
wputl(long l)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
lput(long l)382 lput(long l)
383 {
384 LPUT(l);
385 }
386
387 void
lputl(long c)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
llput(vlong v)401 llput(vlong v)
402 {
403 lput(v>>32);
404 lput(v);
405 }
406
407 void
llputl(vlong v)408 llputl(vlong v)
409 {
410 lputl(v);
411 lputl(v>>32);
412 }
413
414 void
cflush(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
asmsym(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
putsymb(char * s,int t,long v,int ver)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
asmlc(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
datblk(long s,long n)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 }
728