1 #include "l.h"
2
3 void
noops(void)4 noops(void)
5 {
6 Prog *p, *p1, *q, *q1;
7 int o, curframe, curbecome, maxbecome;
8
9 /*
10 * find leaf subroutines
11 * become sizes
12 * frame sizes
13 * strip NOPs
14 * expand RET
15 * expand BECOME pseudo
16 */
17
18 if(debug['v'])
19 Bprint(&bso, "%5.2f noops\n", cputime());
20 Bflush(&bso);
21
22 curframe = 0;
23 curbecome = 0;
24 maxbecome = 0;
25 curtext = 0;
26 q = P;
27 for(p = firstp; p != P; p = p->link) {
28
29 /* find out how much arg space is used in this TEXT */
30 if(p->to.type == D_OREG && p->to.reg == REGSP)
31 if(p->to.offset > curframe)
32 curframe = p->to.offset;
33
34 switch(p->as) {
35 /* too hard, just leave alone */
36 case ATEXT:
37 if(curtext && curtext->from.sym) {
38 curtext->from.sym->frame = curframe;
39 curtext->from.sym->become = curbecome;
40 if(curbecome > maxbecome)
41 maxbecome = curbecome;
42 }
43 curframe = 0;
44 curbecome = 0;
45
46 q = p;
47 p->mark |= LABEL|LEAF|SYNC;
48 if(p->link)
49 p->link->mark |= LABEL;
50 curtext = p;
51 break;
52
53 case AORN:
54 q = p;
55 if(p->to.type == D_REG)
56 if(p->to.reg == REGZERO)
57 p->mark |= LABEL|SYNC;
58 break;
59
60 case AUNIMP:
61 case ATAS:
62 case ASWAP:
63 case ATA:
64 case ATCC:
65 case ATCS:
66 case ATE:
67 case ATG:
68 case ATGE:
69 case ATGU:
70 case ATL:
71 case ATLE:
72 case ATLEU:
73 case ATN:
74 case ATNE:
75 case ATNEG:
76 case ATPOS:
77 case ATVC:
78 case ATVS:
79 case AWORD:
80 q = p;
81 p->mark |= LABEL|SYNC;
82 continue;
83
84 case AFABSD:
85 case AFABSF:
86 case AFABSX:
87 case AFADDD:
88 case AFADDF:
89 case AFADDX:
90 case AFDIVD:
91 case AFDIVF:
92 case AFDIVX:
93 case AFMOVD:
94 case AFMOVDF:
95 case AFMOVDW:
96 case AFMOVDX:
97 case AFMOVF:
98 case AFMOVFD:
99 case AFMOVFW:
100 case AFMOVFX:
101 case AFMOVWD:
102 case AFMOVWF:
103 case AFMOVWX:
104 case AFMOVX:
105 case AFMOVXD:
106 case AFMOVXF:
107 case AFMOVXW:
108 case AFMULD:
109 case AFMULF:
110 case AFMULX:
111 case AFNEGD:
112 case AFNEGF:
113 case AFNEGX:
114 case AFSQRTD:
115 case AFSQRTF:
116 case AFSQRTX:
117 case AFSUBD:
118 case AFSUBF:
119 case AFSUBX:
120 q = p;
121 p->mark |= FLOAT;
122 continue;
123
124 case AMUL:
125 case ADIV:
126 case ADIVL:
127 case AMOD:
128 case AMODL:
129 q = p;
130 if(!debug['M']) {
131 if(prog_mul == P)
132 initmuldiv();
133 if(curtext != P)
134 curtext->mark &= ~LEAF;
135 }
136 continue;
137
138 case AJMPL:
139 if(curtext != P)
140 curtext->mark &= ~LEAF;
141
142 case AJMP:
143
144 case ABA:
145 case ABN:
146 case ABE:
147 case ABNE:
148 case ABLE:
149 case ABG:
150 case ABL:
151 case ABGE:
152 case ABLEU:
153 case ABGU:
154 case ABCS:
155 case ABCC:
156 case ABNEG:
157 case ABPOS:
158 case ABVC:
159 case ABVS:
160
161 case AFBN:
162 case AFBO:
163 case AFBE:
164 case AFBLG:
165 case AFBG:
166 case AFBLE:
167 case AFBGE:
168 case AFBL:
169 case AFBNE:
170 case AFBUE:
171 case AFBA:
172 case AFBU:
173 case AFBUG:
174 case AFBULE:
175 case AFBUGE:
176 case AFBUL:
177 p->mark |= BRANCH;
178 q = p;
179 q1 = p->cond;
180 if(q1 != P) {
181 while(q1->as == ANOP) {
182 q1 = q1->link;
183 p->cond = q1;
184 }
185 if(!(q1->mark & LEAF))
186 q1->mark |= LABEL;
187 } else
188 p->mark |= LABEL;
189 q1 = p->link;
190 if(q1 != P)
191 q1->mark |= LABEL;
192 continue;
193
194 case AFCMPD:
195 case AFCMPED:
196 case AFCMPEF:
197 case AFCMPEX:
198 case AFCMPF:
199 case AFCMPX:
200 q = p;
201 p->mark |= FCMP|FLOAT;
202 continue;
203
204 case ARETURN:
205 /* special form of RETURN is BECOME */
206 if(p->from.type == D_CONST)
207 if(p->from.offset > curbecome)
208 curbecome = p->from.offset;
209
210 q = p;
211 if(p->link != P)
212 p->link->mark |= LABEL;
213 continue;
214
215 case ANOP:
216 q1 = p->link;
217 q->link = q1; /* q is non-nop */
218 q1->mark |= p->mark;
219 continue;
220
221 default:
222 q = p;
223 continue;
224 }
225 }
226 if(curtext && curtext->from.sym) {
227 curtext->from.sym->frame = curframe;
228 curtext->from.sym->become = curbecome;
229 if(curbecome > maxbecome)
230 maxbecome = curbecome;
231 }
232
233 if(debug['b'])
234 print("max become = %d\n", maxbecome);
235 xdefine("ALEFbecome", STEXT, maxbecome);
236
237 curtext = 0;
238 for(p = firstp; p != P; p = p->link) {
239 switch(p->as) {
240 case ATEXT:
241 curtext = p;
242 break;
243
244 case AJMPL:
245 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
246 o = maxbecome - curtext->from.sym->frame;
247 if(o <= 0)
248 break;
249 /* calling a become or calling a variable */
250 if(p->to.sym == S || p->to.sym->become) {
251 curtext->to.offset += o;
252 if(debug['b']) {
253 curp = p;
254 print("%D calling %D increase %d\n",
255 &curtext->from, &p->to, o);
256 }
257 }
258 }
259 break;
260 }
261 }
262
263 curtext = P;
264 for(p = firstp; p != P; p = p->link) {
265 o = p->as;
266 switch(o) {
267 case ATEXT:
268 curtext = p;
269 autosize = p->to.offset + 4;
270 if((p->mark & LEAF) && autosize <= 4)
271 autosize = 0;
272 else
273 if(autosize & 4)
274 autosize += 4;
275 p->to.offset = autosize - 4;
276
277 q = p;
278 if(autosize) {
279 q = prg();
280 q->as = ASUB;
281 q->line = p->line;
282 q->from.type = D_CONST;
283 q->from.offset = autosize;
284 q->to.type = D_REG;
285 q->to.reg = REGSP;
286
287 q->link = p->link;
288 p->link = q;
289 } else
290 if(!(curtext->mark & LEAF)) {
291 if(debug['v'])
292 Bprint(&bso, "save suppressed in: %s\n",
293 curtext->from.sym->name);
294 curtext->mark |= LEAF;
295 }
296
297 if(curtext->mark & LEAF) {
298 if(curtext->from.sym)
299 curtext->from.sym->type = SLEAF;
300 break;
301 }
302
303 q1 = prg();
304 q1->as = AMOVW;
305 q1->line = p->line;
306 q1->from.type = D_REG;
307 q1->from.reg = REGLINK;
308 q1->to.type = D_OREG;
309 q1->from.offset = 0;
310 q1->to.reg = REGSP;
311
312 q1->link = q->link;
313 q->link = q1;
314 break;
315
316 case AMUL:
317 case ADIV:
318 case ADIVL:
319 case AMOD:
320 case AMODL:
321 if(debug['M'])
322 break;
323 if(p->from.type != D_REG)
324 break;
325 if(p->to.type != D_REG)
326 break;
327 q1 = p;
328
329 /* MOV a,4(SP) */
330 q = prg();
331 q->link = p->link;
332 p->link = q;
333 p = q;
334
335 p->as = AMOVW;
336 p->line = q1->line;
337 p->from.type = D_REG;
338 p->from.reg = q1->from.reg;
339 p->to.type = D_OREG;
340 p->to.reg = REGSP;
341 p->to.offset = 4;
342
343 /* MOV b,REGTMP */
344 q = prg();
345 q->link = p->link;
346 p->link = q;
347 p = q;
348
349 p->as = AMOVW;
350 p->line = q1->line;
351 p->from.type = D_REG;
352 p->from.reg = q1->reg;
353 if(q1->reg == NREG)
354 p->from.reg = q1->to.reg;
355 p->to.type = D_REG;
356 p->to.reg = REGTMP;
357 p->to.offset = 0;
358
359 /* CALL appropriate */
360 q = prg();
361 q->link = p->link;
362 p->link = q;
363 p = q;
364
365 p->as = AJMPL;
366 p->line = q1->line;
367 p->to.type = D_BRANCH;
368 p->cond = p;
369 p->mark |= BRANCH;
370 switch(o) {
371 case AMUL:
372 p->cond = prog_mul;
373 break;
374 case ADIV:
375 p->cond = prog_div;
376 break;
377 case ADIVL:
378 p->cond = prog_divl;
379 break;
380 case AMOD:
381 p->cond = prog_mod;
382 break;
383 case AMODL:
384 p->cond = prog_modl;
385 break;
386 }
387
388 /* MOV REGTMP, b */
389 q = prg();
390 q->link = p->link;
391 p->link = q;
392 p = q;
393
394 p->as = AMOVW;
395 p->line = q1->line;
396 p->from.type = D_REG;
397 p->from.reg = REGTMP;
398 p->from.offset = 0;
399 p->to.type = D_REG;
400 p->to.reg = q1->to.reg;
401
402 /* ADD $8,SP */
403 q = prg();
404 q->link = p->link;
405 p->link = q;
406 p = q;
407
408 p->as = AADD;
409 p->from.type = D_CONST;
410 p->from.reg = NREG;
411 p->from.offset = 8;
412 p->reg = NREG;
413 p->to.type = D_REG;
414 p->to.reg = REGSP;
415
416 /* SUB $8,SP */
417 q1->as = ASUB;
418 q1->from.type = D_CONST;
419 q1->from.offset = 8;
420 q1->from.reg = NREG;
421 q1->reg = NREG;
422 q1->to.type = D_REG;
423 q1->to.reg = REGSP;
424 break;
425
426 case ARETURN:
427 if(p->from.type == D_CONST)
428 goto become;
429 if(curtext->mark & LEAF) {
430 if(!autosize) {
431 p->as = AJMP;
432 p->from = zprg.from;
433 p->to.type = D_OREG;
434 p->to.offset = 8;
435 p->to.reg = REGLINK;
436 p->mark |= BRANCH;
437 break;
438 }
439
440 p->as = AADD;
441 p->from.type = D_CONST;
442 p->from.offset = autosize;
443 p->to.type = D_REG;
444 p->to.reg = REGSP;
445
446 q = prg();
447 q->as = AJMP;
448 q->line = p->line;
449 q->to.type = D_OREG;
450 q->to.offset = 8;
451 q->to.reg = REGLINK;
452 q->mark |= BRANCH;
453
454 q->link = p->link;
455 p->link = q;
456 break;
457 }
458
459 p->as = AMOVW;
460 p->from.type = D_OREG;
461 p->from.offset = 0;
462 p->from.reg = REGSP;
463 p->to.type = D_REG;
464 p->to.reg = REGRET+1;
465
466 q = p;
467 if(autosize) {
468 q = prg();
469 q->as = AADD;
470 q->line = p->line;
471 q->from.type = D_CONST;
472 q->from.offset = autosize;
473 q->to.type = D_REG;
474 q->to.reg = REGSP;
475
476 q->link = p->link;
477 p->link = q;
478 }
479
480 q1 = prg();
481 q1->as = AJMP;
482 q1->line = p->line;
483 q1->to.type = D_OREG;
484 q1->to.offset = 8;
485 q1->to.reg = REGRET+1;
486 q1->mark |= BRANCH;
487
488 q1->link = q->link;
489 q->link = q1;
490 break;
491
492 become:
493 if(curtext->mark & LEAF) {
494
495 q = prg();
496 q->line = p->line;
497 q->as = AJMP;
498 q->from = zprg.from;
499 q->to = p->to;
500 q->cond = p->cond;
501 q->link = p->link;
502 q->mark |= BRANCH;
503 p->link = q;
504
505 p->as = AADD;
506 p->from = zprg.from;
507 p->from.type = D_CONST;
508 p->from.offset = autosize;
509 p->to = zprg.to;
510 p->to.type = D_REG;
511 p->to.reg = REGSP;
512
513 break;
514 }
515 q = prg();
516 q->line = p->line;
517 q->as = AJMP;
518 q->from = zprg.from;
519 q->to = p->to;
520 q->cond = p->cond;
521 q->mark |= BRANCH;
522 q->link = p->link;
523 p->link = q;
524
525 q = prg();
526 q->line = p->line;
527 q->as = AADD;
528 q->from.type = D_CONST;
529 q->from.offset = autosize;
530 q->to.type = D_REG;
531 q->to.reg = REGSP;
532 q->link = p->link;
533 p->link = q;
534
535 p->as = AMOVW;
536 p->from = zprg.from;
537 p->from.type = D_OREG;
538 p->from.offset = 0;
539 p->from.reg = REGSP;
540 p->to = zprg.to;
541 p->to.type = D_REG;
542 p->to.reg = REGLINK;
543
544 break;
545 }
546 }
547
548 curtext = P;
549 q = P; /* p - 1 */
550 q1 = firstp; /* top of block */
551 o = 0; /* count of instructions */
552 for(p = firstp; p != P; p = p1) {
553 p1 = p->link;
554 o++;
555 if(p->mark & NOSCHED){
556 if(q1 != p){
557 sched(q1, q);
558 }
559 for(; p != P; p = p->link){
560 if(!(p->mark & NOSCHED))
561 break;
562 q = p;
563 }
564 p1 = p;
565 q1 = p;
566 o = 0;
567 continue;
568 }
569 if(p->mark & (LABEL|SYNC)) {
570 if(q1 != p)
571 sched(q1, q);
572 q1 = p;
573 o = 1;
574 }
575 if(p->mark & (BRANCH|SYNC)) {
576 sched(q1, p);
577 q1 = p1;
578 o = 0;
579 }
580 if(o >= NSCHED) {
581 sched(q1, p);
582 q1 = p1;
583 o = 0;
584 }
585 q = p;
586 }
587 }
588
589 void
addnop(Prog * p)590 addnop(Prog *p)
591 {
592 Prog *q;
593
594 q = prg();
595 q->as = AORN;
596 q->line = p->line;
597 q->from.type = D_REG;
598 q->from.reg = REGZERO;
599 q->to.type = D_REG;
600 q->to.reg = REGZERO;
601
602 q->link = p->link;
603 p->link = q;
604 }
605
606 void
initmuldiv(void)607 initmuldiv(void)
608 {
609 Sym *s1, *s2, *s3, *s4, *s5;
610 Prog *p;
611
612 s1 = lookup("_mul", 0);
613 s2 = lookup("_div", 0);
614 s3 = lookup("_divl", 0);
615 s4 = lookup("_mod", 0);
616 s5 = lookup("_modl", 0);
617 for(p = firstp; p != P; p = p->link)
618 if(p->as == ATEXT) {
619 if(p->from.sym == s1)
620 prog_mul = p;
621 if(p->from.sym == s2)
622 prog_div = p;
623 if(p->from.sym == s3)
624 prog_divl = p;
625 if(p->from.sym == s4)
626 prog_mod = p;
627 if(p->from.sym == s5)
628 prog_modl = p;
629 }
630 if(prog_mul == P) {
631 diag("undefined: %s", s1->name);
632 prog_mul = curtext;
633 }
634 if(prog_div == P) {
635 diag("undefined: %s", s2->name);
636 prog_div = curtext;
637 }
638 if(prog_divl == P) {
639 diag("undefined: %s", s3->name);
640 prog_divl = curtext;
641 }
642 if(prog_mod == P) {
643 diag("undefined: %s", s4->name);
644 prog_mod = curtext;
645 }
646 if(prog_modl == P) {
647 diag("undefined: %s", s5->name);
648 prog_modl = curtext;
649 }
650 }
651