xref: /inferno-os/utils/ql/asm.c (revision e57c7e16a3789cd4de1a3c2560d49b1ee39cd10a)
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) {
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 }
846