]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/1l/span.c
merge
[plan9front.git] / sys / src / cmd / 1l / span.c
1 #include        "l.h"
2
3 void
4 span(void)
5 {
6         Prog *p, *q;
7         long v, c, idat;
8         Optab *o;
9         int m, n;
10
11         xdefine("etext", STEXT, 0L);
12         xdefine("a6base", STEXT, 0L);
13         idat = INITDAT;
14         for(p = firstp; p != P; p = p->link) {
15                 if(p->as == ATEXT)
16                         curtext = p;
17                 n = 0;
18                 if((q = p->pcond) != P)
19                         if(q->back != 2)
20                                 n = 1;
21                 p->back = n;
22                 if(p->as == AADJSP) {
23                         p->to.type = D_A0+7;
24                         v = -p->from.offset;
25                         p->from.offset = v;
26                         if((v < -8 && v >= -32768L) || (v > 8 && v < 32768L)) {
27                                 p->as = ALEA;
28                                 p->from.type = I_INDIR | (D_A0+7);
29                                 continue;
30                         }
31                         p->as = AADDL;
32                         if(v < 0) {
33                                 p->as = ASUBL;
34                                 v = -v;
35                                 p->from.offset = v;
36                         }
37                         if(v >= 0 && v <= 8)
38                                 p->from.type = D_QUICK;
39                         if(v == 0)
40                                 p->as = ANOP;
41                 }
42         }
43         n = 0;
44
45 start:
46         if(debug['v'])
47                 Bprint(&bso, "%5.2f span\n", cputime());
48         Bflush(&bso);
49         c = INITTEXT;
50         for(p = firstp; p != P; p = p->link) {
51                 if(p->as == ATEXT)
52                         curtext = p;
53                 o = &optab[p->as];
54                 p->pc = c;
55                 m = mmsize[o->optype];
56                 if(m == 0) {
57                         if(p->as == AWORD)
58                                 m = 2;
59                         if(p->as == ALONG)
60                                 m = 4;
61                         p->mark = m;
62                         c += m;
63                         continue;
64                 }
65                 if(p->from.type != D_NONE)
66                         m += andsize(p, &p->from);
67                 if(p->to.type == D_BRANCH) {
68                         if(p->pcond == P)
69                                 p->pcond = p;
70                         c += m;
71                         if(m == 2)
72                                 m |= 0100;
73                         p->mark = m;
74                         continue;
75                 }
76                 if(p->to.type != D_NONE)
77                         m += andsize(p, &p->to);
78                 p->mark = m;
79                 c += m;
80         }
81
82 loop:
83         n++;
84         if(debug['v'])
85                 Bprint(&bso, "%5.2f span %d\n", cputime(), n);
86         Bflush(&bso);
87         if(n > 60) {
88                 diag("span must be looping");
89                 errorexit();
90         }
91         c = INITTEXT;
92         for(p = firstp; p != P; p = p->link) {
93                 if(p->as == ATEXT)
94                         curtext = p;
95                 if((m = p->mark) & 0100) {
96                         q = p->pcond;
97                         v = q->pc - 2;
98                         if(p->back)
99                                 v -= c;
100                         else
101                                 v -= p->pc;
102                         p->pc = c;
103                         if(v < -32768L || v >= 32768L) {
104                                 c += 6;         /* only jsr and jmp can do this */
105                         } else
106                         if(v < -128 || v >= 128)
107                                 c += 4;
108                         else
109                         if(v == 0) {
110                                 c += 4;
111                                 p->mark = 4;
112                         } else
113                                 c += 2;
114                         continue;
115                 }
116                 p->pc = c;
117                 c += m;
118         }
119         if(c != textsize) {
120                 textsize = c;
121                 goto loop;
122         }
123         if(INITRND)
124                 INITDAT = rnd(c, INITRND);
125         if(INITDAT != idat) {
126                 idat = INITDAT;
127                 goto start;
128         }
129         xdefine("etext", STEXT, c);
130         xdefine("a6base", STEXT, INITDAT+A6OFFSET);
131         if(debug['v'])
132                 Bprint(&bso, "etext = %lux\n", c);
133         Bflush(&bso);
134         for(p = textp; p != P; p = p->pcond)
135                 p->from.sym->value = p->pc;
136         textsize = c - INITTEXT;
137 }
138
139 void
140 xdefine(char *p, int t, long v)
141 {
142         Sym *s;
143
144         s = lookup(p, 0);
145         if(s->type == 0 || s->type == SXREF) {
146                 s->type = t;
147                 s->value = v;
148         }
149         if(s->type == STEXT && s->value == 0)
150                 s->value = v;
151 }
152
153 int
154 andsize(Prog *p, Adr *ap)
155 {
156         int t, n;
157         long v;
158         Optab *o;
159
160         t = ap->type;
161         n = simple[t];
162         if(n != 0177) {
163                 v = ap->offset;
164                 if(v == 0)
165                         return 0;
166                 if((n&070) != 020)      /* D_INDIR */
167                         return 0;
168                 if(v == 0)
169                         return 0;
170                 return 2;
171         }
172         if((t&I_MASK) == I_ADDR)
173                 t = D_CONST;
174         switch(t) {
175
176         default:
177                 return 0;
178
179         case D_STACK:
180         case D_AUTO:
181         case D_PARAM:
182                 v = ap->offset;
183                 if(v == 0)
184                         return 0;
185                 return 2;
186
187         case I_INDIR|D_CONST:
188                 v = ap->offset;
189                 if(v < -32768L || v >= 32768L)
190                         return 4;
191                 return 2;
192
193         case D_STATIC:
194         case D_EXTERN:
195                 if(ap->sym->type == STEXT) {
196                         if(HEADTYPE == 4)
197                                 return 2;
198                         return 4;
199                 }
200                 v = ap->sym->value + ap->offset - A6OFFSET;
201                 if(v == 0)
202                         return 0;
203                 if(v < -32768L || v >= 32768L)
204                         return 4;
205                 return 2;
206
207         case D_CONST:
208         case D_FCONST:
209                 o = &optab[p->as];
210                 if(ap == &(p->from))
211                         return o->srcsp;
212                 return o->dstsp;
213
214         case D_CCR:
215         case D_SR:
216                 if(p->as == AMOVW)
217                         return 0;
218                 return 2;
219
220         case D_USP:
221                 t = p->from.type;
222                 if(t >= D_A0 && t <= D_A0+8)
223                         return 0;
224                 t = p->to.type;
225                 if(t >= D_A0 && t <= D_A0+8)
226                         return 0;
227
228         case D_SFC:
229         case D_DFC:
230         case D_CACR:
231         case D_VBR:
232         case D_CAAR:
233         case D_MSP:
234         case D_ISP:
235         case D_FPCR:
236         case D_FPSR:
237         case D_FPIAR:
238         case D_TC:
239         case D_ITT0:
240         case D_ITT1:
241         case D_DTT0:
242         case D_DTT1:
243         case D_MMUSR:
244         case D_URP:
245         case D_SRP:
246                 return 2;
247         }
248 }
249
250 void
251 putsymb(Sym *s, int t, long v)
252 {
253         int i, f;
254         char *n;
255
256         n = s->name;
257         if(t == 'f')
258                 n++;
259         lput(v);
260         if(s->version)
261                 t += 'a' - 'A';
262         CPUT(t+0x80);                   /* 0x80 is variable length */
263
264         if(t == 'Z' || t == 'z') {
265                 CPUT(n[0]);
266                 for(i=1; n[i] != 0 || n[i+1] != 0; i += 2) {
267                         CPUT(n[i]);
268                         CPUT(n[i+1]);
269                 }
270                 CPUT(0);
271                 CPUT(0);
272                 i++;
273         }
274         else {
275                 for(i=0; n[i]; i++)
276                         CPUT(n[i]);
277                 CPUT(0);
278         }
279         symsize += 4 + 1 + i + 1;
280
281         if(debug['n']) {
282                 if(t == 'z' || t == 'Z') {
283                         Bprint(&bso, "%c %.8lux ", t, v);
284                         for(i=1; n[i] != 0 || n[i+1] != 0; i+=2) {
285                                 f = ((n[i]&0xff) << 8) | (n[i+1]&0xff);
286                                 Bprint(&bso, "/%x", f);
287                         }
288                         Bprint(&bso, "\n");
289                         return;
290                 }
291                 if(s->version)
292                         Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, n, s->version);
293                 else
294                         Bprint(&bso, "%c %.8lux %s\n", t, v, n);
295         }
296 }
297
298 void
299 asmsym(void)
300 {
301         Prog *p;
302         Auto *a;
303         Sym *s;
304         int h;
305
306         s = lookup("etext", 0);
307         if(s->type == STEXT)
308                 putsymb(s, 'T', s->value);
309         s = lookup("a6base", 0);
310         if(s->type == STEXT)
311                 putsymb(s, 'D', s->value);
312
313         for(h=0; h<NHASH; h++)
314                 for(s=hash[h]; s!=S; s=s->link)
315                         switch(s->type) {
316                         case SDATA:
317                                 putsymb(s, 'D', s->value+INITDAT);
318                                 continue;
319
320                         case SBSS:
321                                 putsymb(s, 'B', s->value+INITDAT);
322                                 continue;
323
324                         case SFILE:
325                                 putsymb(s, 'f', s->value);
326                                 continue;
327                         }
328
329         for(p=textp; p!=P; p=p->pcond) {
330                 s = p->from.sym;
331                 if(s->type != STEXT)
332                         continue;
333
334                 /* filenames first */
335                 for(a=p->to.autom; a; a=a->link)
336                         if(a->type == D_FILE)
337                                 putsymb(a->asym, 'z', a->aoffset);
338                         else
339                         if(a->type == D_FILE1)
340                                 putsymb(a->asym, 'Z', a->aoffset);
341
342                 putsymb(s, 'T', s->value);
343
344                 /* auto and param after */
345                 for(a=p->to.autom; a; a=a->link)
346                         if(a->type == D_AUTO)
347                                 putsymb(a->asym, 'a', -a->aoffset);
348                         else
349                         if(a->type == D_PARAM)
350                                 putsymb(a->asym, 'p', a->aoffset);
351         }
352         if(debug['v'] || debug['n'])
353                 Bprint(&bso, "symsize = %lud\n", symsize);
354         Bflush(&bso);
355 }
356
357 #define MINLC   2
358 void
359 asmsp(void)
360 {
361         long oldpc, oldsp;
362         Prog *p;
363         int s;
364         long v;
365
366         oldpc = INITTEXT;
367         oldsp = 0;
368         for(p = firstp; p != P; p = p->link) {
369                 if(p->stkoff == oldsp || p->as == ATEXT || p->as == ANOP) {
370                         if(p->as == ATEXT)
371                                 curtext = p;
372                         if(debug['G'])
373                                 Bprint(&bso, "%6lux %4ld%P\n",
374                                         p->pc, p->stkoff, p);
375                         continue;
376                 }
377                 if(debug['G'])
378                         Bprint(&bso, "\t\t%6ld", spsize);
379                 v = (p->pc - oldpc) / MINLC;
380                 while(v) {
381                         s = 127;
382                         if(v < 127)
383                                 s = v;
384                         CPUT(s+128);    /* 129-255 +pc */
385                         if(debug['G'])
386                                 Bprint(&bso, " pc+%d*2(%d)", s, s+128);
387                         v -= s;
388                         spsize++;
389                 }
390                 v = p->stkoff - oldsp;
391                 oldsp = p->stkoff;
392                 oldpc = p->pc + MINLC;
393                 if(v & 3 || v > 64L*4L || v < -64L*4L) {
394                         CPUT(0);        /* 0 vvvv +sp */
395                         lput(v);
396                         if(debug['G']) {
397                                 if(v > 0)
398                                         Bprint(&bso, " sp+%ld*1(%d,%ld)\n",
399                                                 v, 0, v);
400                                 else
401                                         Bprint(&bso, " sp%ld*1(%d,%ld)\n",
402                                                 v, 0, v);
403                                 Bprint(&bso, "%6lux %4ld%P\n",
404                                         p->pc, p->stkoff, p);
405                         }
406                         spsize += 5;
407                         continue;
408                 }
409                 s = v/4;
410                 if(s > 0) {
411                         CPUT(0+s);      /* 1-64 +sp */
412                         if(debug['G']) {
413                                 Bprint(&bso, " sp+%d*4(%d)\n", s, 0+s);
414                                 Bprint(&bso, "%6lux %4ld%P\n",
415                                         p->pc, p->stkoff, p);
416                         }
417                 } else {
418                         CPUT(64-s);     /* 65-128 -sp */
419                         if(debug['G']) {
420                                 Bprint(&bso, " sp%d*4(%d)\n", s, 64-s);
421                                 Bprint(&bso, "%6lux %4ld%P\n",
422                                         p->pc, p->stkoff, p);
423                         }
424                 }
425                 spsize++;
426         }
427         while(spsize & 1) {
428                 s = 129;
429                 CPUT(s);
430                 spsize++;
431         }
432         if(debug['v'] || debug['G'])
433                 Bprint(&bso, "stsize = %ld\n", spsize);
434         Bflush(&bso);
435 }
436
437 void
438 asmlc(void)
439 {
440         long oldpc, oldlc;
441         Prog *p;
442         long v, s;
443
444         oldpc = INITTEXT;
445         oldlc = 0;
446         for(p = firstp; p != P; p = p->link) {
447                 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
448                         if(p->as == ATEXT)
449                                 curtext = p;
450                         if(debug['L'])
451                                 Bprint(&bso, "%6lux %P\n",
452                                         p->pc, p);
453                         continue;
454                 }
455                 if(debug['L'])
456                         Bprint(&bso, "\t\t%6ld", lcsize);
457                 v = (p->pc - oldpc) / MINLC;
458                 while(v) {
459                         s = 127;
460                         if(v < 127)
461                                 s = v;
462                         CPUT(s+128);    /* 129-255 +pc */
463                         if(debug['L'])
464                                 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
465                         v -= s;
466                         lcsize++;
467                 }
468                 s = p->line - oldlc;
469                 oldlc = p->line;
470                 oldpc = p->pc + MINLC;
471                 if(s > 64 || s < -64) {
472                         CPUT(0);        /* 0 vv +lc */
473                         CPUT(s>>24);
474                         CPUT(s>>16);
475                         CPUT(s>>8);
476                         CPUT(s);
477                         if(debug['L']) {
478                                 if(s > 0)
479                                         Bprint(&bso, " lc+%ld(%d,%ld)\n",
480                                                 s, 0, s);
481                                 else
482                                         Bprint(&bso, " lc%ld(%d,%ld)\n",
483                                                 s, 0, s);
484                                 Bprint(&bso, "%6lux %P\n",
485                                         p->pc, p);
486                         }
487                         lcsize += 5;
488                         continue;
489                 }
490                 if(s > 0) {
491                         CPUT(0+s);      /* 1-64 +lc */
492                         if(debug['L']) {
493                                 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
494                                 Bprint(&bso, "%6lux %P\n",
495                                         p->pc, p);
496                         }
497                 } else {
498                         CPUT(64-s);     /* 65-128 -lc */
499                         if(debug['L']) {
500                                 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
501                                 Bprint(&bso, "%6lux %P\n",
502                                         p->pc, p);
503                         }
504                 }
505                 lcsize++;
506         }
507         while(lcsize & 1) {
508                 s = 129;
509                 CPUT(s);
510                 lcsize++;
511         }
512         if(debug['v'] || debug['L'])
513                 Bprint(&bso, "lcsize = %ld\n", lcsize);
514         Bflush(&bso);
515 }