xref: /inferno-os/utils/5l/noop.c (revision 50b0dbb170df61467e42c7ea4deb0b5692d15f4c)
1 #include	"l.h"
2 
3 static	Sym*	sym_div;
4 static	Sym*	sym_divu;
5 static	Sym*	sym_mod;
6 static	Sym*	sym_modu;
7 
8 void
9 noops(void)
10 {
11 	Prog *p, *q, *q1;
12 	int o, curframe, curbecome, maxbecome;
13 
14 	/*
15 	 * find leaf subroutines
16 	 * become sizes
17 	 * frame sizes
18 	 * strip NOPs
19 	 * expand RET
20 	 * expand BECOME pseudo
21 	 */
22 
23 	if(debug['v'])
24 		Bprint(&bso, "%5.2f noops\n", cputime());
25 	Bflush(&bso);
26 
27 	curframe = 0;
28 	curbecome = 0;
29 	maxbecome = 0;
30 	curtext = 0;
31 
32 	q = P;
33 	for(p = firstp; p != P; p = p->link) {
34 
35 		/* find out how much arg space is used in this TEXT */
36 		if(p->to.type == D_OREG && p->to.reg == REGSP)
37 			if(p->to.offset > curframe)
38 				curframe = p->to.offset;
39 
40 		switch(p->as) {
41 		case ATEXT:
42 			if(curtext && curtext->from.sym) {
43 				curtext->from.sym->frame = curframe;
44 				curtext->from.sym->become = curbecome;
45 				if(curbecome > maxbecome)
46 					maxbecome = curbecome;
47 			}
48 			curframe = 0;
49 			curbecome = 0;
50 
51 			p->mark |= LEAF;
52 			curtext = p;
53 			break;
54 
55 		case ARET:
56 			/* special form of RET is BECOME */
57 			if(p->from.type == D_CONST)
58 				if(p->from.offset > curbecome)
59 					curbecome = p->from.offset;
60 			break;
61 
62 		case ADIV:
63 		case ADIVU:
64 		case AMOD:
65 		case AMODU:
66 			q = p;
67 			if(prog_div == P)
68 				initdiv();
69 			if(curtext != P)
70 				curtext->mark &= ~LEAF;
71 			continue;
72 
73 		case ANOP:
74 			q1 = p->link;
75 			q->link = q1;		/* q is non-nop */
76 			q1->mark |= p->mark;
77 			continue;
78 
79 		case ABL:
80 			if(curtext != P)
81 				curtext->mark &= ~LEAF;
82 
83 		case ABCASE:
84 		case AB:
85 
86 		case ABEQ:
87 		case ABNE:
88 		case ABCS:
89 		case ABHS:
90 		case ABCC:
91 		case ABLO:
92 		case ABMI:
93 		case ABPL:
94 		case ABVS:
95 		case ABVC:
96 		case ABHI:
97 		case ABLS:
98 		case ABGE:
99 		case ABLT:
100 		case ABGT:
101 		case ABLE:
102 
103 			q1 = p->cond;
104 			if(q1 != P) {
105 				while(q1->as == ANOP) {
106 					q1 = q1->link;
107 					p->cond = q1;
108 				}
109 			}
110 			break;
111 		}
112 		q = p;
113 	}
114 
115 	if(curtext && curtext->from.sym) {
116 		curtext->from.sym->frame = curframe;
117 		curtext->from.sym->become = curbecome;
118 		if(curbecome > maxbecome)
119 			maxbecome = curbecome;
120 	}
121 
122 	if(debug['b'])
123 		print("max become = %d\n", maxbecome);
124 	xdefine("ALEFbecome", STEXT, maxbecome);
125 
126 	curtext = 0;
127 	for(p = firstp; p != P; p = p->link) {
128 		switch(p->as) {
129 		case ATEXT:
130 			curtext = p;
131 			break;
132 		case ABL:
133 			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
134 				o = maxbecome - curtext->from.sym->frame;
135 				if(o <= 0)
136 					break;
137 				/* calling a become or calling a variable */
138 				if(p->to.sym == S || p->to.sym->become) {
139 					curtext->to.offset += o;
140 					if(debug['b']) {
141 						curp = p;
142 						print("%D calling %D increase %d\n",
143 							&curtext->from, &p->to, o);
144 					}
145 				}
146 			}
147 			break;
148 		}
149 	}
150 
151 	for(p = firstp; p != P; p = p->link) {
152 		o = p->as;
153 		switch(o) {
154 		case ATEXT:
155 			curtext = p;
156 			autosize = p->to.offset + 4;
157 			if(autosize <= 4)
158 			if(curtext->mark & LEAF) {
159 				p->to.offset = -4;
160 				autosize = 0;
161 			}
162 
163 			if(!autosize && !(curtext->mark & LEAF)) {
164 				if(debug['v'])
165 					Bprint(&bso, "save suppressed in: %s\n",
166 						curtext->from.sym->name);
167 				Bflush(&bso);
168 				curtext->mark |= LEAF;
169 			}
170 
171 			if(curtext->mark & LEAF) {
172 				if(curtext->from.sym)
173 					curtext->from.sym->type = SLEAF;
174 #ifdef optimise_time
175 				if(autosize) {
176 					q = prg();
177 					q->as = ASUB;
178 					q->line = p->line;
179 					q->from.type = D_CONST;
180 					q->from.offset = autosize;
181 					q->to.type = D_REG;
182 					q->to.reg = REGSP;
183 
184 					q->link = p->link;
185 					p->link = q;
186 				}
187 				break;
188 #else
189 				if(!autosize)
190 					break;
191 #endif
192 			}
193 
194 			q1 = prg();
195 			q1->as = AMOVW;
196 			q1->scond |= C_WBIT;
197 			q1->line = p->line;
198 			q1->from.type = D_REG;
199 			q1->from.reg = REGLINK;
200 			q1->to.type = D_OREG;
201 			q1->to.offset = -autosize;
202 			q1->to.reg = REGSP;
203 
204 			q1->link = p->link;
205 			p->link = q1;
206 			break;
207 
208 		case ARET:
209 			nocache(p);
210 			if(p->from.type == D_CONST)
211 				goto become;
212 			if(curtext->mark & LEAF) {
213 				if(!autosize) {
214 					p->as = AB;
215 					p->from = zprg.from;
216 					p->to.type = D_OREG;
217 					p->to.offset = 0;
218 					p->to.reg = REGLINK;
219 					break;
220 				}
221 
222 #ifdef optimise_time
223 				p->as = AADD;
224 				p->from.type = D_CONST;
225 				p->from.offset = autosize;
226 				p->to.type = D_REG;
227 				p->to.reg = REGSP;
228 
229 				q = prg();
230 				q->as = AB;
231 				q->scond = p->scond;
232 				q->line = p->line;
233 				q->to.type = D_OREG;
234 				q->to.offset = 0;
235 				q->to.reg = REGLINK;
236 
237 				q->link = p->link;
238 				p->link = q;
239 
240 				break;
241 #endif
242 			}
243 			p->as = AMOVW;
244 			p->scond |= C_PBIT;
245 			p->from.type = D_OREG;
246 			p->from.offset = autosize;
247 			p->from.reg = REGSP;
248 			p->to.type = D_REG;
249 			p->to.reg = REGPC;
250 			break;
251 
252 		become:
253 			if(curtext->mark & LEAF) {
254 
255 				if(!autosize) {
256 					p->as = AB;
257 					p->from = zprg.from;
258 					break;
259 				}
260 
261 #ifdef optimise_time
262 				q = prg();
263 				q->scond = p->scond;
264 				q->line = p->line;
265 				q->as = AB;
266 				q->from = zprg.from;
267 				q->to = p->to;
268 				q->cond = p->cond;
269 				q->link = p->link;
270 				p->link = q;
271 
272 				p->as = AADD;
273 				p->from = zprg.from;
274 				p->from.type = D_CONST;
275 				p->from.offset = autosize;
276 				p->to = zprg.to;
277 				p->to.type = D_REG;
278 				p->to.reg = REGSP;
279 
280 				break;
281 #endif
282 			}
283 			q = prg();
284 			q->scond = p->scond;
285 			q->line = p->line;
286 			q->as = AB;
287 			q->from = zprg.from;
288 			q->to = p->to;
289 			q->cond = p->cond;
290 			q->link = p->link;
291 			p->link = q;
292 
293 			p->as = AMOVW;
294 			p->scond |= C_PBIT;
295 			p->from = zprg.from;
296 			p->from.type = D_OREG;
297 			p->from.offset = autosize;
298 			p->from.reg = REGSP;
299 			p->to = zprg.to;
300 			p->to.type = D_REG;
301 			p->to.reg = REGLINK;
302 
303 			break;
304 
305 		/*
306 		 * 5c code generation for unsigned -> double made the
307 		 * unfortunate assumption that single and double floating
308 		 * point registers are aliased - true for emulated 7500
309 		 * but not for vfp.  Now corrected, but this test is
310 		 * insurance against old 5c compiled code in libraries.
311 		 */
312 		case AMOVWD:
313 			if((q = p->link) != P && q->as == ACMP)
314 			if((q = q->link) != P && q->as == AMOVF)
315 			if((q1 = q->link) != P && q1->as == AADDF)
316 			if(q1->to.type == D_FREG && q1->to.reg == p->to.reg) {
317 				q1->as = AADDD;
318 				q1 = prg();
319 				q1->scond = q->scond;
320 				q1->line = q->line;
321 				q1->as = AMOVFD;
322 				q1->from = q->to;
323 				q1->to = q1->from;
324 				q1->link = q->link;
325 				q->link = q1;
326 			}
327 			break;
328 
329 		case ADIV:
330 		case ADIVU:
331 		case AMOD:
332 		case AMODU:
333 			if(debug['M'])
334 				break;
335 			if(p->from.type != D_REG)
336 				break;
337 			if(p->to.type != D_REG)
338 				break;
339 			q1 = p;
340 
341 			/* MOV a,4(SP) */
342 			q = prg();
343 			q->link = p->link;
344 			p->link = q;
345 			p = q;
346 
347 			p->as = AMOVW;
348 			p->line = q1->line;
349 			p->from.type = D_REG;
350 			p->from.reg = q1->from.reg;
351 			p->to.type = D_OREG;
352 			p->to.reg = REGSP;
353 			p->to.offset = 4;
354 
355 			/* MOV b,REGTMP */
356 			q = prg();
357 			q->link = p->link;
358 			p->link = q;
359 			p = q;
360 
361 			p->as = AMOVW;
362 			p->line = q1->line;
363 			p->from.type = D_REG;
364 			p->from.reg = q1->reg;
365 			if(q1->reg == NREG)
366 				p->from.reg = q1->to.reg;
367 			p->to.type = D_REG;
368 			p->to.reg = REGTMP;
369 			p->to.offset = 0;
370 
371 			/* CALL appropriate */
372 			q = prg();
373 			q->link = p->link;
374 			p->link = q;
375 			p = q;
376 
377 			p->as = ABL;
378 			p->line = q1->line;
379 			p->to.type = D_BRANCH;
380 			p->cond = p;
381 			switch(o) {
382 			case ADIV:
383 				p->cond = prog_div;
384 				p->to.sym = sym_div;
385 				break;
386 			case ADIVU:
387 				p->cond = prog_divu;
388 				p->to.sym = sym_divu;
389 				break;
390 			case AMOD:
391 				p->cond = prog_mod;
392 				p->to.sym = sym_mod;
393 				break;
394 			case AMODU:
395 				p->cond = prog_modu;
396 				p->to.sym = sym_modu;
397 				break;
398 			}
399 
400 			/* MOV REGTMP, b */
401 			q = prg();
402 			q->link = p->link;
403 			p->link = q;
404 			p = q;
405 
406 			p->as = AMOVW;
407 			p->line = q1->line;
408 			p->from.type = D_REG;
409 			p->from.reg = REGTMP;
410 			p->from.offset = 0;
411 			p->to.type = D_REG;
412 			p->to.reg = q1->to.reg;
413 
414 			/* ADD $8,SP */
415 			q = prg();
416 			q->link = p->link;
417 			p->link = q;
418 			p = q;
419 
420 			p->as = AADD;
421 			p->from.type = D_CONST;
422 			p->from.reg = NREG;
423 			p->from.offset = 8;
424 			p->reg = NREG;
425 			p->to.type = D_REG;
426 			p->to.reg = REGSP;
427 
428 			/* SUB $8,SP */
429 			q1->as = ASUB;
430 			q1->from.type = D_CONST;
431 			q1->from.offset = 8;
432 			q1->from.reg = NREG;
433 			q1->reg = NREG;
434 			q1->to.type = D_REG;
435 			q1->to.reg = REGSP;
436 			break;
437 		}
438 	}
439 }
440 
441 static void
442 sigdiv(char *n)
443 {
444 	Sym *s;
445 
446 	s = lookup(n, 0);
447 	if(s->type == STEXT){
448 		if(s->sig == 0)
449 			s->sig = SIGNINTERN;
450 	}
451 	else if(s->type == 0 || s->type == SXREF)
452 		s->type = SUNDEF;
453 }
454 
455 void
456 divsig(void)
457 {
458 	sigdiv("_div");
459 	sigdiv("_divu");
460 	sigdiv("_mod");
461 	sigdiv("_modu");
462 }
463 
464 static void
465 sdiv(Sym *s)
466 {
467 	if(s->type == 0 || s->type == SXREF){
468 		/* undefsym(s); */
469 		s->type = SXREF;
470 		if(s->sig == 0)
471 			s->sig = SIGNINTERN;
472 		s->subtype = SIMPORT;
473 	}
474 	else if(s->type != STEXT)
475 		diag("undefined: %s", s->name);
476 }
477 
478 void
479 initdiv(void)
480 {
481 	Sym *s2, *s3, *s4, *s5;
482 	Prog *p;
483 
484 	if(prog_div != P)
485 		return;
486 	sym_div = s2 = lookup("_div", 0);
487 	sym_divu = s3 = lookup("_divu", 0);
488 	sym_mod = s4 = lookup("_mod", 0);
489 	sym_modu = s5 = lookup("_modu", 0);
490 	if(dlm) {
491 		sdiv(s2); if(s2->type == SXREF) prog_div = UP;
492 		sdiv(s3); if(s3->type == SXREF) prog_divu = UP;
493 		sdiv(s4); if(s4->type == SXREF) prog_mod = UP;
494 		sdiv(s5); if(s5->type == SXREF) prog_modu = UP;
495 	}
496 	for(p = firstp; p != P; p = p->link)
497 		if(p->as == ATEXT) {
498 			if(p->from.sym == s2)
499 				prog_div = p;
500 			if(p->from.sym == s3)
501 				prog_divu = p;
502 			if(p->from.sym == s4)
503 				prog_mod = p;
504 			if(p->from.sym == s5)
505 				prog_modu = p;
506 		}
507 	if(prog_div == P) {
508 		diag("undefined: %s", s2->name);
509 		prog_div = curtext;
510 	}
511 	if(prog_divu == P) {
512 		diag("undefined: %s", s3->name);
513 		prog_divu = curtext;
514 	}
515 	if(prog_mod == P) {
516 		diag("undefined: %s", s4->name);
517 		prog_mod = curtext;
518 	}
519 	if(prog_modu == P) {
520 		diag("undefined: %s", s5->name);
521 		prog_modu = curtext;
522 	}
523 }
524 
525 void
526 nocache(Prog *p)
527 {
528 	p->optab = 0;
529 	p->from.class = 0;
530 	p->to.class = 0;
531 }
532