1 #include "l.h"
2
3 void
pagebug(Prog * p)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
span(void)34 span(void)
35 {
36 Prog *p, *q;
37 Sym *setext, *s;
38 Optab *o;
39 int m, bflag, i;
40 vlong 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 + 8;
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 + 8;
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 = %llux\n", textsize);
158 Bflush(&bso);
159 }
160
161 void
xdefine(char * p,int t,vlong v)162 xdefine(char *p, int t, vlong 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
regoff(Adr * a)174 regoff(Adr *a)
175 {
176
177 instoffset = 0;
178 aclass(a);
179 return instoffset;
180 }
181
182 int
isint32(vlong v)183 isint32(vlong v)
184 {
185 long l;
186
187 l = v;
188 return (vlong)l == v;
189 }
190
191 int
isuint32(uvlong v)192 isuint32(uvlong v)
193 {
194 ulong l;
195
196 l = v;
197 return (uvlong)l == v;
198 }
199
200 int
aclass(Adr * a)201 aclass(Adr *a)
202 {
203 Sym *s;
204 int t;
205
206 switch(a->type) {
207 case D_NONE:
208 return C_NONE;
209
210 case D_REG:
211 return C_REG;
212
213 case D_FREG:
214 return C_FREG;
215
216 case D_FCREG:
217 return C_FCREG;
218
219 case D_MREG:
220 return C_MREG;
221
222 case D_OREG:
223 switch(a->name) {
224 case D_EXTERN:
225 case D_STATIC:
226 if(a->sym == 0 || a->sym->name == 0) {
227 print("null sym external\n");
228 print("%D\n", a);
229 return C_GOK;
230 }
231 t = a->sym->type;
232 if(t == 0 || t == SXREF) {
233 diag("undefined external: %s in %s",
234 a->sym->name, TNAME);
235 a->sym->type = SDATA;
236 }
237 instoffset = a->sym->value + a->offset - BIG;
238 if(instoffset >= -BIG && instoffset < BIG)
239 return C_SEXT;
240 return C_LEXT;
241 case D_AUTO:
242 instoffset = autosize + a->offset;
243 if(instoffset >= -BIG && instoffset < BIG)
244 return C_SAUTO;
245 return C_LAUTO;
246
247 case D_PARAM:
248 instoffset = autosize + a->offset + 8L;
249 if(instoffset >= -BIG && instoffset < BIG)
250 return C_SAUTO;
251 return C_LAUTO;
252 case D_NONE:
253 instoffset = a->offset;
254 if(instoffset == 0)
255 return C_ZOREG;
256 if(instoffset >= -BIG && instoffset < BIG)
257 return C_SOREG;
258 return C_LOREG;
259 }
260 return C_GOK;
261
262 case D_HI:
263 return C_LO;
264 case D_LO:
265 return C_HI;
266
267 case D_OCONST:
268 switch(a->name) {
269 case D_EXTERN:
270 case D_STATIC:
271 s = a->sym;
272 t = s->type;
273 if(t == 0 || t == SXREF) {
274 diag("undefined external: %s in %s",
275 s->name, TNAME);
276 s->type = SDATA;
277 }
278 instoffset = s->value + a->offset + INITDAT;
279 if(s->type == STEXT || s->type == SLEAF)
280 instoffset = s->value + a->offset;
281 return C_LCON;
282 }
283 return C_GOK;
284
285 case D_CONST:
286 switch(a->name) {
287 case D_NONE:
288 instoffset = a->offset;
289 consize:
290 if(instoffset > 0) {
291 if(instoffset <= 0x7fff)
292 return C_SCON;
293 if(instoffset <= 0xffff)
294 return C_ANDCON;
295 if((instoffset & 0xffff) == 0 && isuint32(instoffset))
296 return C_UCON;
297 return C_LCON;
298 }
299 if(instoffset == 0)
300 return C_ZCON;
301 if(instoffset >= -0x8000)
302 return C_ADDCON;
303 if((instoffset & 0xffff) == 0 && isint32(instoffset))
304 return C_UCON;
305 return C_LCON;
306
307 case D_EXTERN:
308 case D_STATIC:
309 s = a->sym;
310 if(s == S)
311 break;
312 t = s->type;
313 switch(t) {
314 case 0:
315 case SXREF:
316 diag("undefined external: %s in %s",
317 s->name, TNAME);
318 s->type = SDATA;
319 break;
320 case SCONST:
321 instoffset = s->value + a->offset;
322 goto consize;
323 case STEXT:
324 case SLEAF:
325 instoffset = s->value + a->offset;
326 return C_LCON;
327 }
328 instoffset = s->value + a->offset - BIG;
329 if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)
330 return C_SECON;
331 instoffset = s->value + a->offset + INITDAT;
332 return C_LCON;
333
334 case D_AUTO:
335 instoffset = autosize + a->offset;
336 if(instoffset >= -BIG && instoffset < BIG)
337 return C_SACON;
338 return C_LACON;
339
340 case D_PARAM:
341 instoffset = autosize + a->offset + 8L;
342 if(instoffset >= -BIG && instoffset < BIG)
343 return C_SACON;
344 return C_LACON;
345 }
346 return C_GOK;
347
348 case D_BRANCH:
349 return C_SBRA;
350 }
351 return C_GOK;
352 }
353
354 Optab*
oplook(Prog * p)355 oplook(Prog *p)
356 {
357 int a1, a2, a3, r;
358 char *c1, *c3;
359 Optab *o, *e;
360
361 a1 = p->optab;
362 if(a1)
363 return optab+(a1-1);
364 a1 = p->from.class;
365 if(a1 == 0) {
366 a1 = aclass(&p->from) + 1;
367 p->from.class = a1;
368 }
369 a1--;
370 a3 = p->to.class;
371 if(a3 == 0) {
372 a3 = aclass(&p->to) + 1;
373 p->to.class = a3;
374 }
375 a3--;
376 a2 = C_NONE;
377 if(p->reg != NREG)
378 a2 = C_REG;
379 r = p->as;
380 o = oprange[r].start;
381 if(o == 0) {
382 a1 = opcross[repop[r]][a1][a2][a3];
383 if(a1) {
384 p->optab = a1+1;
385 return optab+a1;
386 }
387 o = oprange[r].stop; /* just generate an error */
388 }
389 e = oprange[r].stop;
390 c1 = xcmp[a1];
391 c3 = xcmp[a3];
392 for(; o<e; o++)
393 if(o->a2 == a2)
394 if(c1[o->a1])
395 if(c3[o->a3]) {
396 p->optab = (o-optab)+1;
397 return o;
398 }
399 diag("illegal combination %A %d %d %d",
400 p->as, p->from.class-1, a2, a3);
401 if(!debug['a'])
402 prasm(p);
403 o = optab;
404 p->optab = (o-optab)+1;
405 return o;
406 }
407
408 int
cmp(int a,int b)409 cmp(int a, int b)
410 {
411
412 if(a == b)
413 return 1;
414 switch(a) {
415 case C_LCON:
416 if(b == C_ZCON || b == C_SCON || b == C_UCON ||
417 b == C_ADDCON || b == C_ANDCON)
418 return 1;
419 break;
420 case C_ADD0CON:
421 if(b == C_ADDCON)
422 return 1;
423 case C_ADDCON:
424 if(b == C_ZCON || b == C_SCON)
425 return 1;
426 break;
427 case C_AND0CON:
428 if(b == C_ANDCON)
429 return 1;
430 case C_ANDCON:
431 if(b == C_ZCON || b == C_SCON)
432 return 1;
433 break;
434 case C_UCON:
435 if(b == C_ZCON)
436 return 1;
437 break;
438 case C_SCON:
439 if(b == C_ZCON)
440 return 1;
441 break;
442 case C_LACON:
443 if(b == C_SACON)
444 return 1;
445 break;
446 case C_LBRA:
447 if(b == C_SBRA)
448 return 1;
449 break;
450 case C_LEXT:
451 if(b == C_SEXT)
452 return 1;
453 break;
454 case C_LAUTO:
455 if(b == C_SAUTO)
456 return 1;
457 break;
458 case C_REG:
459 if(b == C_ZCON)
460 return 1;
461 break;
462 case C_LOREG:
463 if(b == C_ZOREG || b == C_SOREG)
464 return 1;
465 break;
466 case C_SOREG:
467 if(b == C_ZOREG)
468 return 1;
469 break;
470 }
471 return 0;
472 }
473
474 int
ocmp(const void * a1,const void * a2)475 ocmp(const void *a1, const void *a2)
476 {
477 Optab *p1, *p2;
478 int n;
479
480 p1 = (Optab*)a1;
481 p2 = (Optab*)a2;
482 n = p1->as - p2->as;
483 if(n)
484 return n;
485 n = p1->a1 - p2->a1;
486 if(n)
487 return n;
488 n = p1->a2 - p2->a2;
489 if(n)
490 return n;
491 n = p1->a3 - p2->a3;
492 if(n)
493 return n;
494 return 0;
495 }
496
497 void
buildop(void)498 buildop(void)
499 {
500 int i, n, r;
501
502 for(i=0; i<32; i++)
503 for(n=0; n<32; n++)
504 xcmp[i][n] = cmp(n, i);
505 for(n=0; optab[n].as != AXXX; n++)
506 ;
507 qsort(optab, n, sizeof(optab[0]), ocmp);
508 for(i=0; i<n; i++) {
509 r = optab[i].as;
510 oprange[r].start = optab+i;
511 while(optab[i].as == r)
512 i++;
513 oprange[r].stop = optab+i;
514 i--;
515
516 switch(r)
517 {
518 default:
519 diag("unknown op in build: %A", r);
520 errorexit();
521 case AABSF:
522 oprange[AMOVFD] = oprange[r];
523 oprange[AMOVDF] = oprange[r];
524 oprange[AMOVWF] = oprange[r];
525 oprange[AMOVFW] = oprange[r];
526 oprange[AMOVWD] = oprange[r];
527 oprange[AMOVDW] = oprange[r];
528 oprange[ANEGF] = oprange[r];
529 oprange[ANEGD] = oprange[r];
530 oprange[AABSD] = oprange[r];
531 oprange[ATRUNCDW] = oprange[r];
532 oprange[ATRUNCFW] = oprange[r];
533 oprange[ATRUNCDV] = oprange[r];
534 oprange[ATRUNCFV] = oprange[r];
535 oprange[AMOVDV] = oprange[r];
536 oprange[AMOVFV] = oprange[r];
537 oprange[AMOVVD] = oprange[r];
538 oprange[AMOVVF] = oprange[r];
539 break;
540 case AADD:
541 buildrep(1, AADD);
542 oprange[ASGT] = oprange[r];
543 repop[ASGT] = 1;
544 oprange[ASGTU] = oprange[r];
545 repop[ASGTU] = 1;
546 oprange[AADDU] = oprange[r];
547 repop[AADDU] = 1;
548 oprange[AADDVU] = oprange[r];
549 repop[AADDVU] = 1;
550 oprange[AADDV] = oprange[r];
551 repop[AADDV] = 1;
552 break;
553 case AADDF:
554 oprange[ADIVF] = oprange[r];
555 oprange[ADIVD] = oprange[r];
556 oprange[AMULF] = oprange[r];
557 oprange[AMULD] = oprange[r];
558 oprange[ASUBF] = oprange[r];
559 oprange[ASUBD] = oprange[r];
560 oprange[AADDD] = oprange[r];
561 break;
562 case AAND:
563 buildrep(2, AAND);
564 oprange[AXOR] = oprange[r];
565 repop[AXOR] = 2;
566 oprange[AOR] = oprange[r];
567 repop[AOR] = 2;
568 break;
569 case ABEQ:
570 oprange[ABNE] = oprange[r];
571 break;
572 case ABLEZ:
573 oprange[ABGEZ] = oprange[r];
574 oprange[ABGEZAL] = oprange[r];
575 oprange[ABLTZ] = oprange[r];
576 oprange[ABLTZAL] = oprange[r];
577 oprange[ABGTZ] = oprange[r];
578 break;
579 case AMOVB:
580 buildrep(3, AMOVB);
581 oprange[AMOVH] = oprange[r];
582 repop[AMOVH] = 3;
583 break;
584 case AMOVBU:
585 buildrep(4, AMOVBU);
586 oprange[AMOVHU] = oprange[r];
587 repop[AMOVHU] = 4;
588 break;
589 case AMUL:
590 oprange[AREM] = oprange[r];
591 oprange[AREMU] = oprange[r];
592 oprange[ADIVU] = oprange[r];
593 oprange[AMULU] = oprange[r];
594 oprange[ADIV] = oprange[r];
595 oprange[ADIVV] = oprange[r];
596 oprange[ADIVVU] = oprange[r];
597 oprange[AMULV] = oprange[r];
598 oprange[AMULVU] = oprange[r];
599 oprange[AREMV] = oprange[r];
600 oprange[AREMVU] = oprange[r];
601 break;
602 case ASLL:
603 oprange[ASRL] = oprange[r];
604 oprange[ASRA] = oprange[r];
605 oprange[ASLLV] = oprange[r];
606 oprange[ASRAV] = oprange[r];
607 oprange[ASRLV] = oprange[r];
608 break;
609 case ASUB:
610 oprange[ASUBU] = oprange[r];
611 oprange[ASUBV] = oprange[r];
612 oprange[ASUBVU] = oprange[r];
613 oprange[ANOR] = oprange[r];
614 break;
615 case ASYSCALL:
616 oprange[ATLBP] = oprange[r];
617 oprange[ATLBR] = oprange[r];
618 oprange[ATLBWI] = oprange[r];
619 oprange[ATLBWR] = oprange[r];
620 break;
621 case ACMPEQF:
622 oprange[ACMPGTF] = oprange[r];
623 oprange[ACMPGTD] = oprange[r];
624 oprange[ACMPGEF] = oprange[r];
625 oprange[ACMPGED] = oprange[r];
626 oprange[ACMPEQD] = oprange[r];
627 break;
628 case ABFPT:
629 oprange[ABFPF] = oprange[r];
630 break;
631 case AMOVWL:
632 oprange[AMOVWR] = oprange[r];
633 oprange[AMOVVR] = oprange[r];
634 oprange[AMOVVL] = oprange[r];
635 break;
636 case AMOVW:
637 buildrep(5, AMOVW);
638 break;
639 case AMOVD:
640 buildrep(6, AMOVD);
641 break;
642 case AMOVF:
643 buildrep(7, AMOVF);
644 break;
645 case AMOVV:
646 buildrep(8, AMOVV);
647 break;
648 case ABREAK:
649 case AWORD:
650 case ARFE:
651 case AJAL:
652 case AJMP:
653 case ATEXT:
654 case ACASE:
655 case ABCASE:
656 case AMOVWU:
657 break;
658 }
659 }
660 }
661
662 void
buildrep(int x,int as)663 buildrep(int x, int as)
664 {
665 Opcross *p;
666 Optab *e, *s, *o;
667 int a1, a2, a3, n;
668
669 if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
670 diag("assumptions fail in buildrep");
671 errorexit();
672 }
673 repop[as] = x;
674 p = (opcross + x);
675 s = oprange[as].start;
676 e = oprange[as].stop;
677 for(o=e-1; o>=s; o--) {
678 n = o-optab;
679 for(a2=0; a2<2; a2++) {
680 if(a2) {
681 if(o->a2 == C_NONE)
682 continue;
683 } else
684 if(o->a2 != C_NONE)
685 continue;
686 for(a1=0; a1<32; a1++) {
687 if(!xcmp[a1][o->a1])
688 continue;
689 for(a3=0; a3<32; a3++)
690 if(xcmp[a3][o->a3])
691 (*p)[a1][a2][a3] = n;
692 }
693 }
694 }
695 oprange[as].start = 0;
696 }
697