]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vl/span.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / vl / span.c
1 #include        "l.h"
2
3 void
4 pagebug(Prog *p)
5 {
6         Prog *q;
7
8         switch(p->as) {
9         case ABGEZAL:
10         case ABLTZAL:
11         case AJAL:
12         case ABEQ:
13         case ABGEZ:
14         case ABGTZ:
15         case ABLEZ:
16         case ABLTZ:
17         case ABNE:
18         case ABFPT:
19         case ABFPF:
20         case AJMP:
21                 q = prg();
22                 *q = *p;
23                 p->link = q;
24                 p->as = ANOR;
25                 p->optab = 0;
26                 p->from = zprg.from;
27                 p->from.type = D_REG;
28                 p->from.reg = REGZERO;
29                 p->to = p->from;
30         }
31 }
32
33 void
34 span(void)
35 {
36         Prog *p, *q;
37         Sym *setext, *s;
38         Optab *o;
39         int m, bflag, i;
40         long c, otxt, v;
41
42         if(debug['v'])
43                 Bprint(&bso, "%5.2f span\n", cputime());
44         Bflush(&bso);
45
46         bflag = 0;
47         c = INITTEXT;
48         otxt = c;
49         for(p = firstp; p != P; p = p->link) {
50                 /* bug in early 4000 chips delayslot on page boundary */
51                 if((c&(0x1000-1)) == 0xffc)
52                         pagebug(p);
53                 p->pc = c;
54                 o = oplook(p);
55                 m = o->size;
56                 if(m == 0) {
57                         if(p->as == ATEXT) {
58                                 curtext = p;
59                                 autosize = p->to.offset + 4;
60                                 if(p->from.sym != S)
61                                         p->from.sym->value = c;
62                                 /* need passes to resolve branches */
63                                 if(c-otxt >= 1L<<17)
64                                         bflag = 1;
65                                 otxt = c;
66                                 continue;
67                         }
68                         diag("zero-width instruction\n%P", p);
69                         continue;
70                 }
71                 c += m;
72         }
73
74         /*
75          * if any procedure is large enough to
76          * generate a large SBRA branch, then
77          * generate extra passes putting branches
78          * around jmps to fix. this is rare.
79          */
80         while(bflag) {
81                 if(debug['v'])
82                         Bprint(&bso, "%5.2f span1\n", cputime());
83                 bflag = 0;
84                 c = INITTEXT;
85                 for(p = firstp; p != P; p = p->link) {
86                         /* bug in early 4000 chips delayslot on page boundary */
87                         if((c&(0x1000-1)) == 0xffc)
88                                 pagebug(p);
89                         p->pc = c;
90                         o = oplook(p);
91                         if(o->type == 6 && p->cond) {
92                                 otxt = p->cond->pc - c;
93                                 if(otxt < 0)
94                                         otxt = -otxt;
95                                 if(otxt >= (1L<<17) - 10) {
96                                         q = prg();
97                                         q->link = p->link;
98                                         p->link = q;
99                                         q->as = AJMP;
100                                         q->to.type = D_BRANCH;
101                                         q->cond = p->cond;
102                                         p->cond = q;
103                                         q = prg();
104                                         q->link = p->link;
105                                         p->link = q;
106                                         q->as = AJMP;
107                                         q->to.type = D_BRANCH;
108                                         q->cond = q->link->link;
109                                         addnop(p->link);
110                                         addnop(p);
111                                         bflag = 1;
112                                 }
113                         }
114                         m = o->size;
115                         if(m == 0) {
116                                 if(p->as == ATEXT) {
117                                         curtext = p;
118                                         autosize = p->to.offset + 4;
119                                         if(p->from.sym != S)
120                                                 p->from.sym->value = c;
121                                         continue;
122                                 }
123                                 diag("zero-width instruction\n%P", p);
124                                 continue;
125                         }
126                         c += m;
127                 }
128         }
129
130         if(debug['t']) {
131                 /* 
132                  * add strings to text segment
133                  */
134                 c = rnd(c, 8);
135                 for(i=0; i<NHASH; i++)
136                 for(s = hash[i]; s != S; s = s->link) {
137                         if(s->type != SSTRING)
138                                 continue;
139                         v = s->value;
140                         while(v & 3)
141                                 v++;
142                         s->value = c;
143                         c += v;
144                 }
145         }
146
147         c = rnd(c, 8);
148
149         setext = lookup("etext", 0);
150         if(setext != S) {
151                 setext->value = c;
152                 textsize = c - INITTEXT;
153         }
154         if(INITRND)
155                 INITDAT = rnd(c, INITRND);
156         if(debug['v'])
157                 Bprint(&bso, "tsize = %lux\n", textsize);
158         Bflush(&bso);
159 }
160                 
161 void
162 xdefine(char *p, int t, long v)
163 {
164         Sym *s;
165
166         s = lookup(p, 0);
167         if(s->type == 0 || s->type == SXREF) {
168                 s->type = t;
169                 s->value = v;
170         }
171 }
172
173 long
174 regoff(Adr *a)
175 {
176
177         instoffset = 0;
178         aclass(a);
179         return instoffset;
180 }
181
182 aclass(Adr *a)
183 {
184         Sym *s;
185         int t;
186
187         switch(a->type) {
188         case D_NONE:
189                 return C_NONE;
190
191         case D_REG:
192                 return C_REG;
193
194         case D_FREG:
195                 return C_FREG;
196
197         case D_FCREG:
198                 return C_FCREG;
199
200         case D_MREG:
201                 return C_MREG;
202
203         case D_OREG:
204                 switch(a->name) {
205                 case D_EXTERN:
206                 case D_STATIC:
207                         if(a->sym == 0 || a->sym->name == 0) {
208                                 print("null sym external\n");
209                                 print("%D\n", a);
210                                 return C_GOK;
211                         }
212                         t = a->sym->type;
213                         if(t == 0 || t == SXREF) {
214                                 diag("undefined external: %s in %s",
215                                         a->sym->name, TNAME);
216                                 a->sym->type = SDATA;
217                         }
218                         instoffset = a->sym->value + a->offset - BIG;
219                         if(instoffset >= -BIG && instoffset < BIG)
220                                 return C_SEXT;
221                         return C_LEXT;
222                 case D_AUTO:
223                         instoffset = autosize + a->offset;
224                         if(instoffset >= -BIG && instoffset < BIG)
225                                 return C_SAUTO;
226                         return C_LAUTO;
227
228                 case D_PARAM:
229                         instoffset = autosize + a->offset + 4L;
230                         if(instoffset >= -BIG && instoffset < BIG)
231                                 return C_SAUTO;
232                         return C_LAUTO;
233                 case D_NONE:
234                         instoffset = a->offset;
235                         if(instoffset == 0)
236                                 return C_ZOREG;
237                         if(instoffset >= -BIG && instoffset < BIG)
238                                 return C_SOREG;
239                         return C_LOREG;
240                 }
241                 return C_GOK;
242
243         case D_HI:
244                 return C_LO;
245         case D_LO:
246                 return C_HI;
247
248         case D_OCONST:
249                 switch(a->name) {
250                 case D_EXTERN:
251                 case D_STATIC:
252                         s = a->sym;
253                         t = s->type;
254                         if(t == 0 || t == SXREF) {
255                                 diag("undefined external: %s in %s",
256                                         s->name, TNAME);
257                                 s->type = SDATA;
258                         }
259                         instoffset = s->value + a->offset + INITDAT;
260                         if(s->type == STEXT || s->type == SLEAF)
261                                 instoffset = s->value + a->offset;
262                         return C_LCON;
263                 }
264                 return C_GOK;
265
266         case D_CONST:
267                 switch(a->name) {
268
269                 case D_NONE:
270                         instoffset = a->offset;
271                 consize:
272                         if(instoffset > 0) {
273                                 if(instoffset <= 0x7fff)
274                                         return C_SCON;
275                                 if(instoffset <= 0xffff)
276                                         return C_ANDCON;
277                                 if((instoffset & 0xffff) == 0)
278                                         return C_UCON;
279                                 return C_LCON;
280                         }
281                         if(instoffset == 0)
282                                 return C_ZCON;
283                         if(instoffset >= -0x8000)
284                                 return C_ADDCON;
285                         if((instoffset & 0xffff) == 0)
286                                 return C_UCON;
287                         return C_LCON;
288
289                 case D_EXTERN:
290                 case D_STATIC:
291                         s = a->sym;
292                         if(s == S)
293                                 break;
294                         t = s->type;
295                         switch(t) {
296                         case 0:
297                         case SXREF:
298                                 diag("undefined external: %s in %s",
299                                         s->name, TNAME);
300                                 s->type = SDATA;
301                                 break;
302                         case SCONST:
303                                 instoffset = s->value + a->offset;
304                                 goto consize;
305                         case STEXT:
306                         case SLEAF:
307                         case SSTRING:
308                                 instoffset = s->value + a->offset;
309                                 return C_LCON;
310                         }
311                         instoffset = s->value + a->offset - BIG;
312                         if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)
313                                 return C_SECON;
314                         instoffset = s->value + a->offset + INITDAT;
315                         return C_LCON;
316
317                 case D_AUTO:
318                         instoffset = autosize + a->offset;
319                         if(instoffset >= -BIG && instoffset < BIG)
320                                 return C_SACON;
321                         return C_LACON;
322
323                 case D_PARAM:
324                         instoffset = autosize + a->offset + 4L;
325                         if(instoffset >= -BIG && instoffset < BIG)
326                                 return C_SACON;
327                         return C_LACON;
328                 }
329                 return C_GOK;
330
331         case D_BRANCH:
332                 return C_SBRA;
333         }
334         return C_GOK;
335 }
336
337 Optab*
338 oplook(Prog *p)
339 {
340         int a1, a2, a3, r;
341         char *c1, *c3;
342         Optab *o, *e;
343
344         a1 = p->optab;
345         if(a1)
346                 return optab+(a1-1);
347         a1 = p->from.class;
348         if(a1 == 0) {
349                 a1 = aclass(&p->from) + 1;
350                 p->from.class = a1;
351         }
352         a1--;
353         a3 = p->to.class;
354         if(a3 == 0) {
355                 a3 = aclass(&p->to) + 1;
356                 p->to.class = a3;
357         }
358         a3--;
359         a2 = C_NONE;
360         if(p->reg != NREG)
361                 a2 = C_REG;
362         r = p->as;
363         o = oprange[r].start;
364         if(o == 0) {
365                 a1 = opcross[repop[r]][a1][a2][a3];
366                 if(a1) {
367                         p->optab = a1+1;
368                         return optab+a1;
369                 }
370                 o = oprange[r].stop; /* just generate an error */
371         }
372         e = oprange[r].stop;
373         c1 = xcmp[a1];
374         c3 = xcmp[a3];
375         for(; o<e; o++)
376                 if(o->a2 == a2)
377                 if(c1[o->a1])
378                 if(c3[o->a3]) {
379                         p->optab = (o-optab)+1;
380                         return o;
381                 }
382         diag("illegal combination %A %d %d %d",
383                 p->as, a1, a2, a3);
384         if(!debug['a'])
385                 prasm(p);
386         o = optab;
387         p->optab = (o-optab)+1;
388         return o;
389 }
390
391 int
392 cmp(int a, int b)
393 {
394
395         if(a == b)
396                 return 1;
397         switch(a) {
398         case C_LCON:
399                 if(b == C_ZCON || b == C_SCON || b == C_UCON ||
400                    b == C_ADDCON || b == C_ANDCON)
401                         return 1;
402                 break;
403         case C_ADD0CON:
404                 if(b == C_ADDCON)
405                         return 1;
406         case C_ADDCON:
407                 if(b == C_ZCON || b == C_SCON)
408                         return 1;
409                 break;
410         case C_AND0CON:
411                 if(b == C_ANDCON)
412                         return 1;
413         case C_ANDCON:
414                 if(b == C_ZCON || b == C_SCON)
415                         return 1;
416                 break;
417         case C_UCON:
418                 if(b == C_ZCON)
419                         return 1;
420                 break;
421         case C_SCON:
422                 if(b == C_ZCON)
423                         return 1;
424                 break;
425         case C_LACON:
426                 if(b == C_SACON)
427                         return 1;
428                 break;
429         case C_LBRA:
430                 if(b == C_SBRA)
431                         return 1;
432                 break;
433         case C_LEXT:
434                 if(b == C_SEXT)
435                         return 1;
436                 break;
437         case C_LAUTO:
438                 if(b == C_SAUTO)
439                         return 1;
440                 break;
441         case C_REG:
442                 if(b == C_ZCON)
443                         return 1;
444                 break;
445         case C_LOREG:
446                 if(b == C_ZOREG || b == C_SOREG)
447                         return 1;
448                 break;
449         case C_SOREG:
450                 if(b == C_ZOREG)
451                         return 1;
452                 break;
453         }
454         return 0;
455 }
456
457 int
458 ocmp(const void *a1, const void *a2)
459 {
460         Optab *p1, *p2;
461         int n;
462
463         p1 = (Optab*)a1;
464         p2 = (Optab*)a2;
465         n = p1->as - p2->as;
466         if(n)
467                 return n;
468         n = p1->a1 - p2->a1;
469         if(n)
470                 return n;
471         n = p1->a2 - p2->a2;
472         if(n)
473                 return n;
474         n = p1->a3 - p2->a3;
475         if(n)
476                 return n;
477         return 0;
478 }
479
480 void
481 buildop(void)
482 {
483         int i, n, r;
484
485         for(i=0; i<32; i++)
486                 for(n=0; n<32; n++)
487                         xcmp[i][n] = cmp(n, i);
488         for(n=0; optab[n].as != AXXX; n++)
489                 ;
490         qsort(optab, n, sizeof(optab[0]), ocmp);
491         for(i=0; i<n; i++) {
492                 r = optab[i].as;
493                 oprange[r].start = optab+i;
494                 while(optab[i].as == r)
495                         i++;
496                 oprange[r].stop = optab+i;
497                 i--;
498                 
499                 switch(r)
500                 {
501                 default:
502                         diag("unknown op in build: %A", r);
503                         errorexit();
504                 case AABSF:
505                         oprange[AMOVFD] = oprange[r];
506                         oprange[AMOVDF] = oprange[r];
507                         oprange[AMOVWF] = oprange[r];
508                         oprange[AMOVFW] = oprange[r];
509                         oprange[AMOVWD] = oprange[r];
510                         oprange[AMOVDW] = oprange[r];
511                         oprange[ANEGF] = oprange[r];
512                         oprange[ANEGD] = oprange[r];
513                         oprange[AABSD] = oprange[r];
514                         break;
515                 case AADD:
516                         buildrep(1, AADD);
517                         oprange[ASGT] = oprange[r];
518                         repop[ASGT] = 1;
519                         oprange[ASGTU] = oprange[r];
520                         repop[ASGTU] = 1;
521                         oprange[AADDU] = oprange[r];
522                         repop[AADDU] = 1;
523                         oprange[AADDVU] = oprange[r];
524                         repop[AADDVU] = 1;
525                         break;
526                 case AADDF:
527                         oprange[ADIVF] = oprange[r];
528                         oprange[ADIVD] = oprange[r];
529                         oprange[AMULF] = oprange[r];
530                         oprange[AMULD] = oprange[r];
531                         oprange[ASUBF] = oprange[r];
532                         oprange[ASUBD] = oprange[r];
533                         oprange[AADDD] = oprange[r];
534                         break;
535                 case AAND:
536                         buildrep(2, AAND);
537                         oprange[AXOR] = oprange[r];
538                         repop[AXOR] = 2;
539                         oprange[AOR] = oprange[r];
540                         repop[AOR] = 2;
541                         break;
542                 case ABEQ:
543                         oprange[ABNE] = oprange[r];
544                         break;
545                 case ABLEZ:
546                         oprange[ABGEZ] = oprange[r];
547                         oprange[ABGEZAL] = oprange[r];
548                         oprange[ABLTZ] = oprange[r];
549                         oprange[ABLTZAL] = oprange[r];
550                         oprange[ABGTZ] = oprange[r];
551                         break;
552                 case AMOVB:
553                         buildrep(3, AMOVB);
554                         oprange[AMOVH] = oprange[r];
555                         repop[AMOVH] = 3;
556                         break;
557                 case AMOVBU:
558                         buildrep(4, AMOVBU);
559                         oprange[AMOVHU] = oprange[r];
560                         repop[AMOVHU] = 4;
561                         break;
562                 case AMUL:
563                         oprange[AREM] = oprange[r];
564                         oprange[AREMU] = oprange[r];
565                         oprange[ADIVU] = oprange[r];
566                         oprange[AMULU] = oprange[r];
567                         oprange[ADIV] = oprange[r];
568                         oprange[ADIVVU] = oprange[r];
569                         oprange[ADIVV] = oprange[r];
570                         break;
571                 case ASLL:
572                         oprange[ASRL] = oprange[r];
573                         oprange[ASRA] = oprange[r];
574                         oprange[ASLLV] = oprange[r];
575                         oprange[ASRAV] = oprange[r];
576                         oprange[ASRLV] = oprange[r];
577                         break;
578                 case ASUB:
579                         oprange[ASUBU] = oprange[r];
580                         oprange[ANOR] = oprange[r];
581                         break;
582                 case ASYSCALL:
583                         oprange[ATLBP] = oprange[r];
584                         oprange[ATLBR] = oprange[r];
585                         oprange[ATLBWI] = oprange[r];
586                         oprange[ATLBWR] = oprange[r];
587                         break;
588                 case ACMPEQF:
589                         oprange[ACMPGTF] = oprange[r];
590                         oprange[ACMPGTD] = oprange[r];
591                         oprange[ACMPGEF] = oprange[r];
592                         oprange[ACMPGED] = oprange[r];
593                         oprange[ACMPEQD] = oprange[r];
594                         break;
595                 case ABFPT:
596                         oprange[ABFPF] = oprange[r];
597                         break;
598                 case AMOVWL:
599                         oprange[AMOVWR] = oprange[r];
600                         oprange[AMOVVR] = oprange[r];
601                         oprange[AMOVVL] = oprange[r];
602                         break;
603                 case AMOVW:
604                         buildrep(5, AMOVW);
605                         break;
606                 case AMOVD:
607                         buildrep(6, AMOVD);
608                         break;
609                 case AMOVF:
610                         buildrep(7, AMOVF);
611                         break;
612                 case AMOVV:
613                         buildrep(8, AMOVV);
614                         break;
615                 case ABREAK:
616                 case AWORD:
617                 case ARFE:
618                 case AJAL:
619                 case AJMP:
620                 case ATEXT:
621                 case ACASE:
622                 case ABCASE:
623                         break;
624                 }
625         }
626 }
627
628 void
629 buildrep(int x, int as)
630 {
631         Opcross *p;
632         Optab *e, *s, *o;
633         int a1, a2, a3, n;
634
635         if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
636                 diag("assumptions fail in buildrep");
637                 errorexit();
638         }
639         repop[as] = x;
640         p = (opcross + x);
641         s = oprange[as].start;
642         e = oprange[as].stop;
643         for(o=e-1; o>=s; o--) {
644                 n = o-optab;
645                 for(a2=0; a2<2; a2++) {
646                         if(a2) {
647                                 if(o->a2 == C_NONE)
648                                         continue;
649                         } else
650                                 if(o->a2 != C_NONE)
651                                         continue;
652                         for(a1=0; a1<32; a1++) {
653                                 if(!xcmp[a1][o->a1])
654                                         continue;
655                                 for(a3=0; a3<32; a3++)
656                                         if(xcmp[a3][o->a3])
657                                                 (*p)[a1][a2][a3] = n;
658                         }
659                 }
660         }
661         oprange[as].start = 0;
662 }