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