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