xref: /inferno-os/utils/6l/asm.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
1b370703fSCharles.Forsyth #include	"l.h"
2b370703fSCharles.Forsyth 
3b370703fSCharles.Forsyth #define	Dbufslop	100
4b370703fSCharles.Forsyth 
5*45a20ab7Sforsyth #define PADDR(a)	((a) & ~0xfffffffff0000000ull)
6b370703fSCharles.Forsyth 
72303ddadSforsyth vlong
entryvalue(void)8b370703fSCharles.Forsyth entryvalue(void)
9b370703fSCharles.Forsyth {
10b370703fSCharles.Forsyth 	char *a;
11b370703fSCharles.Forsyth 	Sym *s;
12b370703fSCharles.Forsyth 
13b370703fSCharles.Forsyth 	a = INITENTRY;
14b370703fSCharles.Forsyth 	if(*a >= '0' && *a <= '9')
15b370703fSCharles.Forsyth 		return atolwhex(a);
16b370703fSCharles.Forsyth 	s = lookup(a, 0);
17b370703fSCharles.Forsyth 	if(s->type == 0)
18b370703fSCharles.Forsyth 		return INITTEXT;
19b370703fSCharles.Forsyth 	switch(s->type) {
20b370703fSCharles.Forsyth 	case STEXT:
21b370703fSCharles.Forsyth 		break;
22b370703fSCharles.Forsyth 	case SDATA:
23b370703fSCharles.Forsyth 		if(dlm)
24b370703fSCharles.Forsyth 			return s->value+INITDAT;
25b370703fSCharles.Forsyth 	default:
26b370703fSCharles.Forsyth 		diag("entry not text: %s", s->name);
27b370703fSCharles.Forsyth 	}
28b370703fSCharles.Forsyth 	return s->value;
29b370703fSCharles.Forsyth }
30b370703fSCharles.Forsyth 
31*45a20ab7Sforsyth /* these need to take long arguments to be compatible with elf.c */void
wputl(long w)32*45a20ab7Sforsyth wputl(long w)
33b370703fSCharles.Forsyth {
34b370703fSCharles.Forsyth 	cput(w);
35b370703fSCharles.Forsyth 	cput(w>>8);
36b370703fSCharles.Forsyth }
37b370703fSCharles.Forsyth 
38b370703fSCharles.Forsyth void
wput(long w)39*45a20ab7Sforsyth wput(long w)
40b370703fSCharles.Forsyth {
41b370703fSCharles.Forsyth 	cput(w>>8);
42b370703fSCharles.Forsyth 	cput(w);
43b370703fSCharles.Forsyth }
44b370703fSCharles.Forsyth 
45b370703fSCharles.Forsyth void
lput(long l)46b370703fSCharles.Forsyth lput(long l)
47b370703fSCharles.Forsyth {
48b370703fSCharles.Forsyth 	cput(l>>24);
49b370703fSCharles.Forsyth 	cput(l>>16);
50b370703fSCharles.Forsyth 	cput(l>>8);
51b370703fSCharles.Forsyth 	cput(l);
52b370703fSCharles.Forsyth }
53b370703fSCharles.Forsyth 
54b370703fSCharles.Forsyth void
llput(vlong v)552303ddadSforsyth llput(vlong v)
562303ddadSforsyth {
572303ddadSforsyth 	lput(v>>32);
582303ddadSforsyth 	lput(v);
592303ddadSforsyth }
602303ddadSforsyth 
612303ddadSforsyth void
lputl(long l)62b370703fSCharles.Forsyth lputl(long l)
63b370703fSCharles.Forsyth {
64b370703fSCharles.Forsyth 	cput(l);
65b370703fSCharles.Forsyth 	cput(l>>8);
66b370703fSCharles.Forsyth 	cput(l>>16);
67b370703fSCharles.Forsyth 	cput(l>>24);
68b370703fSCharles.Forsyth }
69b370703fSCharles.Forsyth 
70b370703fSCharles.Forsyth void
llputl(vlong v)71*45a20ab7Sforsyth llputl(vlong v)
72*45a20ab7Sforsyth {
73*45a20ab7Sforsyth 	lputl(v);
74*45a20ab7Sforsyth 	lputl(v>>32);
75*45a20ab7Sforsyth }
76*45a20ab7Sforsyth 
77*45a20ab7Sforsyth void
strnput(char * s,int n)78b370703fSCharles.Forsyth strnput(char *s, int n)
79b370703fSCharles.Forsyth {
80b370703fSCharles.Forsyth 	for(; *s && n > 0; s++){
81b370703fSCharles.Forsyth 		cput(*s);
82b370703fSCharles.Forsyth 		n--;
83b370703fSCharles.Forsyth 	}
84b370703fSCharles.Forsyth 	while(n > 0){
85b370703fSCharles.Forsyth 		cput(0);
86b370703fSCharles.Forsyth 		n--;
87b370703fSCharles.Forsyth 	}
88b370703fSCharles.Forsyth }
89b370703fSCharles.Forsyth 
90b370703fSCharles.Forsyth void
asmb(void)91b370703fSCharles.Forsyth asmb(void)
92b370703fSCharles.Forsyth {
93b370703fSCharles.Forsyth 	Prog *p;
94b370703fSCharles.Forsyth 	long v, magic;
95b370703fSCharles.Forsyth 	int a;
96b370703fSCharles.Forsyth 	uchar *op1;
972303ddadSforsyth 	vlong vl;
98b370703fSCharles.Forsyth 
99b370703fSCharles.Forsyth 	if(debug['v'])
100b370703fSCharles.Forsyth 		Bprint(&bso, "%5.2f asmb\n", cputime());
101b370703fSCharles.Forsyth 	Bflush(&bso);
102b370703fSCharles.Forsyth 
103b370703fSCharles.Forsyth 	seek(cout, HEADR, 0);
104b370703fSCharles.Forsyth 	pc = INITTEXT;
105b370703fSCharles.Forsyth 	curp = firstp;
106b370703fSCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
107b370703fSCharles.Forsyth 		if(p->as == ATEXT)
108b370703fSCharles.Forsyth 			curtext = p;
109b370703fSCharles.Forsyth 		if(p->pc != pc) {
110b370703fSCharles.Forsyth 			if(!debug['a'])
111b370703fSCharles.Forsyth 				print("%P\n", curp);
112b370703fSCharles.Forsyth 			diag("phase error %llux sb %llux in %s", p->pc, pc, TNAME);
113b370703fSCharles.Forsyth 			pc = p->pc;
114b370703fSCharles.Forsyth 		}
115b370703fSCharles.Forsyth 		curp = p;
116b370703fSCharles.Forsyth 		asmins(p);
117b370703fSCharles.Forsyth 		a = (andptr - and);
118b370703fSCharles.Forsyth 		if(cbc < a)
119b370703fSCharles.Forsyth 			cflush();
120b370703fSCharles.Forsyth 		if(debug['a']) {
121b370703fSCharles.Forsyth 			Bprint(&bso, pcstr, pc);
122b370703fSCharles.Forsyth 			for(op1 = and; op1 < andptr; op1++)
123b370703fSCharles.Forsyth 				Bprint(&bso, "%.2ux", *op1 & 0xff);
124b370703fSCharles.Forsyth 			Bprint(&bso, "\t%P\n", curp);
125b370703fSCharles.Forsyth 		}
126b370703fSCharles.Forsyth 		if(dlm) {
127b370703fSCharles.Forsyth 			if(p->as == ATEXT)
128b370703fSCharles.Forsyth 				reloca = nil;
129b370703fSCharles.Forsyth 			else if(reloca != nil)
130b370703fSCharles.Forsyth 				diag("reloc failure: %P", curp);
131b370703fSCharles.Forsyth 		}
132b370703fSCharles.Forsyth 		memmove(cbp, and, a);
133b370703fSCharles.Forsyth 		cbp += a;
134b370703fSCharles.Forsyth 		pc += a;
135b370703fSCharles.Forsyth 		cbc -= a;
136b370703fSCharles.Forsyth 	}
137b370703fSCharles.Forsyth 	cflush();
138b370703fSCharles.Forsyth 	switch(HEADTYPE) {
139b370703fSCharles.Forsyth 	default:
140b370703fSCharles.Forsyth 		diag("unknown header type %ld", HEADTYPE);
141b370703fSCharles.Forsyth 	case 2:
142b370703fSCharles.Forsyth 	case 5:
143*45a20ab7Sforsyth 	case 6:
144b370703fSCharles.Forsyth 		seek(cout, HEADR+textsize, 0);
145b370703fSCharles.Forsyth 		break;
146b370703fSCharles.Forsyth 	}
147b370703fSCharles.Forsyth 
148b370703fSCharles.Forsyth 	if(debug['v'])
149b370703fSCharles.Forsyth 		Bprint(&bso, "%5.2f datblk\n", cputime());
150b370703fSCharles.Forsyth 	Bflush(&bso);
151b370703fSCharles.Forsyth 
152b370703fSCharles.Forsyth 	if(dlm){
153b370703fSCharles.Forsyth 		char buf[8];
154b370703fSCharles.Forsyth 
155b370703fSCharles.Forsyth 		write(cout, buf, INITDAT-textsize);
156b370703fSCharles.Forsyth 		textsize = INITDAT;
157b370703fSCharles.Forsyth 	}
158b370703fSCharles.Forsyth 
159b370703fSCharles.Forsyth 	for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
160b370703fSCharles.Forsyth 		if(datsize-v > sizeof(buf)-Dbufslop)
161b370703fSCharles.Forsyth 			datblk(v, sizeof(buf)-Dbufslop);
162b370703fSCharles.Forsyth 		else
163b370703fSCharles.Forsyth 			datblk(v, datsize-v);
164b370703fSCharles.Forsyth 	}
165b370703fSCharles.Forsyth 
166b370703fSCharles.Forsyth 	symsize = 0;
167b370703fSCharles.Forsyth 	spsize = 0;
168b370703fSCharles.Forsyth 	lcsize = 0;
169b370703fSCharles.Forsyth 	if(!debug['s']) {
170b370703fSCharles.Forsyth 		if(debug['v'])
171b370703fSCharles.Forsyth 			Bprint(&bso, "%5.2f sym\n", cputime());
172b370703fSCharles.Forsyth 		Bflush(&bso);
173b370703fSCharles.Forsyth 		switch(HEADTYPE) {
174b370703fSCharles.Forsyth 		default:
175b370703fSCharles.Forsyth 		case 2:
176b370703fSCharles.Forsyth 		case 5:
177*45a20ab7Sforsyth 		case 6:
178b370703fSCharles.Forsyth 			seek(cout, HEADR+textsize+datsize, 0);
179b370703fSCharles.Forsyth 			break;
180b370703fSCharles.Forsyth 		}
181b370703fSCharles.Forsyth 		if(!debug['s'])
182b370703fSCharles.Forsyth 			asmsym();
183b370703fSCharles.Forsyth 		if(debug['v'])
184b370703fSCharles.Forsyth 			Bprint(&bso, "%5.2f sp\n", cputime());
185b370703fSCharles.Forsyth 		Bflush(&bso);
186b370703fSCharles.Forsyth 		if(debug['v'])
187b370703fSCharles.Forsyth 			Bprint(&bso, "%5.2f pc\n", cputime());
188b370703fSCharles.Forsyth 		Bflush(&bso);
189b370703fSCharles.Forsyth 		if(!debug['s'])
190b370703fSCharles.Forsyth 			asmlc();
191b370703fSCharles.Forsyth 		if(dlm)
192b370703fSCharles.Forsyth 			asmdyn();
193b370703fSCharles.Forsyth 		cflush();
194b370703fSCharles.Forsyth 	}
195b370703fSCharles.Forsyth 	else if(dlm){
196b370703fSCharles.Forsyth 		seek(cout, HEADR+textsize+datsize, 0);
197b370703fSCharles.Forsyth 		asmdyn();
198b370703fSCharles.Forsyth 		cflush();
199b370703fSCharles.Forsyth 	}
200b370703fSCharles.Forsyth 	if(debug['v'])
201b370703fSCharles.Forsyth 		Bprint(&bso, "%5.2f headr\n", cputime());
202b370703fSCharles.Forsyth 	Bflush(&bso);
203b370703fSCharles.Forsyth 	seek(cout, 0L, 0);
204b370703fSCharles.Forsyth 	switch(HEADTYPE) {
205b370703fSCharles.Forsyth 	default:
2062303ddadSforsyth 	case 2:	/* plan9 */
2072303ddadSforsyth 		magic = 4*26*26+7;
2082303ddadSforsyth 		magic |= 0x00008000;		/* fat header */
2092303ddadSforsyth 		if(dlm)
2102303ddadSforsyth 			magic |= 0x80000000;	/* dlm */
2112303ddadSforsyth 		lput(magic);			/* magic */
2122303ddadSforsyth 		lput(textsize);			/* sizes */
213b370703fSCharles.Forsyth 		lput(datsize);
214b370703fSCharles.Forsyth 		lput(bsssize);
2152303ddadSforsyth 		lput(symsize);			/* nsyms */
2162303ddadSforsyth 		vl = entryvalue();
2172303ddadSforsyth 		lput(PADDR(vl));		/* va of entry */
2182303ddadSforsyth 		lput(spsize);			/* sp offsets */
2192303ddadSforsyth 		lput(lcsize);			/* line offsets */
2202303ddadSforsyth 		llput(vl);			/* va of entry */
221b370703fSCharles.Forsyth 		break;
222b370703fSCharles.Forsyth 	case 5:
223*45a20ab7Sforsyth 		elf32(debug['8']? I386: AMD64, ELFDATA2LSB, 0, nil);
224*45a20ab7Sforsyth 		break;
225*45a20ab7Sforsyth 	case 6:
226*45a20ab7Sforsyth 		elf64(AMD64, ELFDATA2LSB, 0, nil);
227b370703fSCharles.Forsyth 		break;
228b370703fSCharles.Forsyth 	}
229b370703fSCharles.Forsyth 	cflush();
230b370703fSCharles.Forsyth }
231b370703fSCharles.Forsyth 
232b370703fSCharles.Forsyth void
cflush(void)233b370703fSCharles.Forsyth cflush(void)
234b370703fSCharles.Forsyth {
235b370703fSCharles.Forsyth 	int n;
236b370703fSCharles.Forsyth 
237b370703fSCharles.Forsyth 	n = sizeof(buf.cbuf) - cbc;
238b370703fSCharles.Forsyth 	if(n)
239b370703fSCharles.Forsyth 		write(cout, buf.cbuf, n);
240b370703fSCharles.Forsyth 	cbp = buf.cbuf;
241b370703fSCharles.Forsyth 	cbc = sizeof(buf.cbuf);
242b370703fSCharles.Forsyth }
243b370703fSCharles.Forsyth 
244b370703fSCharles.Forsyth void
datblk(long s,long n)245b370703fSCharles.Forsyth datblk(long s, long n)
246b370703fSCharles.Forsyth {
247b370703fSCharles.Forsyth 	Prog *p;
248b370703fSCharles.Forsyth 	uchar *cast;
249b370703fSCharles.Forsyth 	long l, fl, j;
250b370703fSCharles.Forsyth 	vlong o;
251b370703fSCharles.Forsyth 	int i, c;
252b370703fSCharles.Forsyth 
253b370703fSCharles.Forsyth 	memset(buf.dbuf, 0, n+Dbufslop);
254b370703fSCharles.Forsyth 	for(p = datap; p != P; p = p->link) {
255b370703fSCharles.Forsyth 		curp = p;
256b370703fSCharles.Forsyth 		l = p->from.sym->value + p->from.offset - s;
257b370703fSCharles.Forsyth 		c = p->from.scale;
258b370703fSCharles.Forsyth 		i = 0;
259b370703fSCharles.Forsyth 		if(l < 0) {
260b370703fSCharles.Forsyth 			if(l+c <= 0)
261b370703fSCharles.Forsyth 				continue;
262b370703fSCharles.Forsyth 			while(l < 0) {
263b370703fSCharles.Forsyth 				l++;
264b370703fSCharles.Forsyth 				i++;
265b370703fSCharles.Forsyth 			}
266b370703fSCharles.Forsyth 		}
267b370703fSCharles.Forsyth 		if(l >= n)
268b370703fSCharles.Forsyth 			continue;
269b370703fSCharles.Forsyth 		if(p->as != AINIT && p->as != ADYNT) {
270b370703fSCharles.Forsyth 			for(j=l+(c-i)-1; j>=l; j--)
271b370703fSCharles.Forsyth 				if(buf.dbuf[j]) {
272b370703fSCharles.Forsyth 					print("%P\n", p);
273b370703fSCharles.Forsyth 					diag("multiple initialization");
274b370703fSCharles.Forsyth 					break;
275b370703fSCharles.Forsyth 				}
276b370703fSCharles.Forsyth 		}
277b370703fSCharles.Forsyth 		switch(p->to.type) {
278b370703fSCharles.Forsyth 		case D_FCONST:
279b370703fSCharles.Forsyth 			switch(c) {
280b370703fSCharles.Forsyth 			default:
281b370703fSCharles.Forsyth 			case 4:
282b370703fSCharles.Forsyth 				fl = ieeedtof(&p->to.ieee);
283b370703fSCharles.Forsyth 				cast = (uchar*)&fl;
284b370703fSCharles.Forsyth 				if(debug['a'] && i == 0) {
285b370703fSCharles.Forsyth 					Bprint(&bso, pcstr, l+s+INITDAT);
286b370703fSCharles.Forsyth 					for(j=0; j<c; j++)
287b370703fSCharles.Forsyth 						Bprint(&bso, "%.2ux", cast[fnuxi4[j]]);
288b370703fSCharles.Forsyth 					Bprint(&bso, "\t%P\n", curp);
289b370703fSCharles.Forsyth 				}
290b370703fSCharles.Forsyth 				for(; i<c; i++) {
291b370703fSCharles.Forsyth 					buf.dbuf[l] = cast[fnuxi4[i]];
292b370703fSCharles.Forsyth 					l++;
293b370703fSCharles.Forsyth 				}
294b370703fSCharles.Forsyth 				break;
295b370703fSCharles.Forsyth 			case 8:
296b370703fSCharles.Forsyth 				cast = (uchar*)&p->to.ieee;
297b370703fSCharles.Forsyth 				if(debug['a'] && i == 0) {
298b370703fSCharles.Forsyth 					Bprint(&bso, pcstr, l+s+INITDAT);
299b370703fSCharles.Forsyth 					for(j=0; j<c; j++)
300b370703fSCharles.Forsyth 						Bprint(&bso, "%.2ux", cast[fnuxi8[j]]);
301b370703fSCharles.Forsyth 					Bprint(&bso, "\t%P\n", curp);
302b370703fSCharles.Forsyth 				}
303b370703fSCharles.Forsyth 				for(; i<c; i++) {
304b370703fSCharles.Forsyth 					buf.dbuf[l] = cast[fnuxi8[i]];
305b370703fSCharles.Forsyth 					l++;
306b370703fSCharles.Forsyth 				}
307b370703fSCharles.Forsyth 				break;
308b370703fSCharles.Forsyth 			}
309b370703fSCharles.Forsyth 			break;
310b370703fSCharles.Forsyth 
311b370703fSCharles.Forsyth 		case D_SCONST:
312b370703fSCharles.Forsyth 			if(debug['a'] && i == 0) {
313b370703fSCharles.Forsyth 				Bprint(&bso, pcstr, l+s+INITDAT);
314b370703fSCharles.Forsyth 				for(j=0; j<c; j++)
315b370703fSCharles.Forsyth 					Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
316b370703fSCharles.Forsyth 				Bprint(&bso, "\t%P\n", curp);
317b370703fSCharles.Forsyth 			}
318b370703fSCharles.Forsyth 			for(; i<c; i++) {
319b370703fSCharles.Forsyth 				buf.dbuf[l] = p->to.scon[i];
320b370703fSCharles.Forsyth 				l++;
321b370703fSCharles.Forsyth 			}
322b370703fSCharles.Forsyth 			break;
323b370703fSCharles.Forsyth 		default:
324b370703fSCharles.Forsyth 			o = p->to.offset;
325b370703fSCharles.Forsyth 			if(p->to.type == D_ADDR) {
326b370703fSCharles.Forsyth 				if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
327b370703fSCharles.Forsyth 					diag("DADDR type%P", p);
328b370703fSCharles.Forsyth 				if(p->to.sym) {
329b370703fSCharles.Forsyth 					if(p->to.sym->type == SUNDEF)
330b370703fSCharles.Forsyth 						ckoff(p->to.sym, o);
331b370703fSCharles.Forsyth 					o += p->to.sym->value;
332b370703fSCharles.Forsyth 					if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
333b370703fSCharles.Forsyth 						o += INITDAT;
334b370703fSCharles.Forsyth 					if(dlm)
335b370703fSCharles.Forsyth 						dynreloc(p->to.sym, l+s+INITDAT, 1);
336b370703fSCharles.Forsyth 				}
337b370703fSCharles.Forsyth 			}
338b370703fSCharles.Forsyth 			fl = o;
339b370703fSCharles.Forsyth 			cast = (uchar*)&fl;
340b370703fSCharles.Forsyth 			switch(c) {
341b370703fSCharles.Forsyth 			default:
342b370703fSCharles.Forsyth 				diag("bad nuxi %d %d\n%P", c, i, curp);
343b370703fSCharles.Forsyth 				break;
344b370703fSCharles.Forsyth 			case 1:
345b370703fSCharles.Forsyth 				if(debug['a'] && i == 0) {
346b370703fSCharles.Forsyth 					Bprint(&bso, pcstr, l+s+INITDAT);
347b370703fSCharles.Forsyth 					for(j=0; j<c; j++)
348b370703fSCharles.Forsyth 						Bprint(&bso, "%.2ux", cast[inuxi1[j]]);
349b370703fSCharles.Forsyth 					Bprint(&bso, "\t%P\n", curp);
350b370703fSCharles.Forsyth 				}
351b370703fSCharles.Forsyth 				for(; i<c; i++) {
352b370703fSCharles.Forsyth 					buf.dbuf[l] = cast[inuxi1[i]];
353b370703fSCharles.Forsyth 					l++;
354b370703fSCharles.Forsyth 				}
355b370703fSCharles.Forsyth 				break;
356b370703fSCharles.Forsyth 			case 2:
357b370703fSCharles.Forsyth 				if(debug['a'] && i == 0) {
358b370703fSCharles.Forsyth 					Bprint(&bso, pcstr, l+s+INITDAT);
359b370703fSCharles.Forsyth 					for(j=0; j<c; j++)
360b370703fSCharles.Forsyth 						Bprint(&bso, "%.2ux", cast[inuxi2[j]]);
361b370703fSCharles.Forsyth 					Bprint(&bso, "\t%P\n", curp);
362b370703fSCharles.Forsyth 				}
363b370703fSCharles.Forsyth 				for(; i<c; i++) {
364b370703fSCharles.Forsyth 					buf.dbuf[l] = cast[inuxi2[i]];
365b370703fSCharles.Forsyth 					l++;
366b370703fSCharles.Forsyth 				}
367b370703fSCharles.Forsyth 				break;
368b370703fSCharles.Forsyth 			case 4:
369b370703fSCharles.Forsyth 				if(debug['a'] && i == 0) {
370b370703fSCharles.Forsyth 					Bprint(&bso, pcstr, l+s+INITDAT);
371b370703fSCharles.Forsyth 					for(j=0; j<c; j++)
372b370703fSCharles.Forsyth 						Bprint(&bso, "%.2ux", cast[inuxi4[j]]);
373b370703fSCharles.Forsyth 					Bprint(&bso, "\t%P\n", curp);
374b370703fSCharles.Forsyth 				}
375b370703fSCharles.Forsyth 				for(; i<c; i++) {
376b370703fSCharles.Forsyth 					buf.dbuf[l] = cast[inuxi4[i]];
377b370703fSCharles.Forsyth 					l++;
378b370703fSCharles.Forsyth 				}
379b370703fSCharles.Forsyth 				break;
380b370703fSCharles.Forsyth 			case 8:
381b370703fSCharles.Forsyth 				cast = (uchar*)&o;
382b370703fSCharles.Forsyth 				if(debug['a'] && i == 0) {
383b370703fSCharles.Forsyth 					Bprint(&bso, pcstr, l+s+INITDAT);
384b370703fSCharles.Forsyth 					for(j=0; j<c; j++)
385b370703fSCharles.Forsyth 						Bprint(&bso, "%.2ux", cast[inuxi8[j]]);
386b370703fSCharles.Forsyth 					Bprint(&bso, "\t%P\n", curp);
387b370703fSCharles.Forsyth 				}
388b370703fSCharles.Forsyth 				for(; i<c; i++) {
389b370703fSCharles.Forsyth 					buf.dbuf[l] = cast[inuxi8[i]];
390b370703fSCharles.Forsyth 					l++;
391b370703fSCharles.Forsyth 				}
392b370703fSCharles.Forsyth 				break;
393b370703fSCharles.Forsyth 			}
394b370703fSCharles.Forsyth 			break;
395b370703fSCharles.Forsyth 		}
396b370703fSCharles.Forsyth 	}
397b370703fSCharles.Forsyth 	write(cout, buf.dbuf, n);
398b370703fSCharles.Forsyth }
399b370703fSCharles.Forsyth 
4002303ddadSforsyth vlong
rnd(vlong v,vlong r)4012303ddadSforsyth rnd(vlong v, vlong r)
402b370703fSCharles.Forsyth {
4032303ddadSforsyth 	vlong c;
404b370703fSCharles.Forsyth 
405b370703fSCharles.Forsyth 	if(r <= 0)
406b370703fSCharles.Forsyth 		return v;
407b370703fSCharles.Forsyth 	v += r - 1;
408b370703fSCharles.Forsyth 	c = v % r;
409b370703fSCharles.Forsyth 	if(c < 0)
410b370703fSCharles.Forsyth 		c += r;
411b370703fSCharles.Forsyth 	v -= c;
412b370703fSCharles.Forsyth 	return v;
413b370703fSCharles.Forsyth }
414