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