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 + 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 = %llux\n", textsize);
158 Bflush(&bso);
159 }
160
161 void
xdefine(char * p,int t,long v)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
regoff(Adr * a)174 regoff(Adr *a)
175 {
176
177 instoffset = 0;
178 aclass(a);
179 return instoffset;
180 }
181
aclass(Adr * a)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*
oplook(Prog * p)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
cmp(int a,int b)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
ocmp(const void * a1,const void * a2)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
buildop(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
buildrep(int x,int as)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 }
663