Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}