xref: /plan9/sys/src/cmd/vl/noop.c (revision 0400b64795cb7922fbea5587531527b381e1e588)
13e12c5d1SDavid du Colombier #include	"l.h"
23e12c5d1SDavid du Colombier 
358b97a46SDavid du Colombier /*
458b97a46SDavid du Colombier  * flag: insert nops to prevent three consecutive stores.
558b97a46SDavid du Colombier  * workaround for 24k erratum #48, costs about 10% in text space,
6*0400b647SDavid du Colombier  * so only enable this if you need it.  test cases are "hoc -e '7^6'"
7*0400b647SDavid du Colombier  * and "{ echo moon; echo plot } | scat".
858b97a46SDavid du Colombier  */
958b97a46SDavid du Colombier enum {
1058b97a46SDavid du Colombier 	Mips24k	= 0,
1158b97a46SDavid du Colombier };
1258b97a46SDavid du Colombier 
1358b97a46SDavid du Colombier static int
isdblwrdmov(Prog * p)1458b97a46SDavid du Colombier isdblwrdmov(Prog *p)
1558b97a46SDavid du Colombier {
1658b97a46SDavid du Colombier 	if(p == nil)
1758b97a46SDavid du Colombier 		return 0;
1858b97a46SDavid du Colombier 	switch(p->as){
1958b97a46SDavid du Colombier 	case AMOVD:
2058b97a46SDavid du Colombier 	case AMOVDF:
2158b97a46SDavid du Colombier 	case AMOVDW:
2258b97a46SDavid du Colombier 	case AMOVFD:
2358b97a46SDavid du Colombier 	case AMOVWD:
2458b97a46SDavid du Colombier 	case AMOVV:
2558b97a46SDavid du Colombier 	case AMOVVL:
2658b97a46SDavid du Colombier 	case AMOVVR:
2758b97a46SDavid du Colombier 	case AMOVFV:
2858b97a46SDavid du Colombier 	case AMOVDV:
2958b97a46SDavid du Colombier 	case AMOVVF:
3058b97a46SDavid du Colombier 	case AMOVVD:
3158b97a46SDavid du Colombier 		return 1;
3258b97a46SDavid du Colombier 	}
3358b97a46SDavid du Colombier 	return 0;
3458b97a46SDavid du Colombier }
3558b97a46SDavid du Colombier 
3658b97a46SDavid du Colombier static int
ismove(Prog * p)3758b97a46SDavid du Colombier ismove(Prog *p)
3858b97a46SDavid du Colombier {
3958b97a46SDavid du Colombier 	if(p == nil)
4058b97a46SDavid du Colombier 		return 0;
4158b97a46SDavid du Colombier 	switch(p->as){
4258b97a46SDavid du Colombier 	case AMOVB:
4358b97a46SDavid du Colombier 	case AMOVBU:
4458b97a46SDavid du Colombier 	case AMOVF:
4558b97a46SDavid du Colombier 	case AMOVFW:
4658b97a46SDavid du Colombier 	case AMOVH:
4758b97a46SDavid du Colombier 	case AMOVHU:
4858b97a46SDavid du Colombier 	case AMOVW:
4958b97a46SDavid du Colombier 	case AMOVWF:
5058b97a46SDavid du Colombier 	case AMOVWL:
5158b97a46SDavid du Colombier 	case AMOVWR:
5258b97a46SDavid du Colombier 	case AMOVWU:
5358b97a46SDavid du Colombier 		return 1;
5458b97a46SDavid du Colombier 	}
5558b97a46SDavid du Colombier 	if(isdblwrdmov(p))
5658b97a46SDavid du Colombier 		return 1;
5758b97a46SDavid du Colombier 	return 0;
5858b97a46SDavid du Colombier }
5958b97a46SDavid du Colombier 
6058b97a46SDavid du Colombier static int
isstore(Prog * p)6158b97a46SDavid du Colombier isstore(Prog *p)
6258b97a46SDavid du Colombier {
6358b97a46SDavid du Colombier 	if(p == nil)
6458b97a46SDavid du Colombier 		return 0;
6558b97a46SDavid du Colombier 	if(ismove(p))
6658b97a46SDavid du Colombier 		switch(p->to.type) {
6758b97a46SDavid du Colombier 		case D_OREG:
6858b97a46SDavid du Colombier 		case D_EXTERN:
6958b97a46SDavid du Colombier 		case D_STATIC:
7058b97a46SDavid du Colombier 		case D_AUTO:
7158b97a46SDavid du Colombier 		case D_PARAM:
7258b97a46SDavid du Colombier 			return 1;
7358b97a46SDavid du Colombier 		}
7458b97a46SDavid du Colombier 	return 0;
7558b97a46SDavid du Colombier }
7658b97a46SDavid du Colombier 
7758b97a46SDavid du Colombier static int
iscondbranch(Prog * p)7858b97a46SDavid du Colombier iscondbranch(Prog *p)
7958b97a46SDavid du Colombier {
8058b97a46SDavid du Colombier 	if(p == nil)
8158b97a46SDavid du Colombier 		return 0;
8258b97a46SDavid du Colombier 	switch(p->as){
8358b97a46SDavid du Colombier 	case ABEQ:
8458b97a46SDavid du Colombier 	case ABFPF:
8558b97a46SDavid du Colombier 	case ABFPT:
8658b97a46SDavid du Colombier 	case ABGEZ:
8758b97a46SDavid du Colombier 	case ABGEZAL:
8858b97a46SDavid du Colombier 	case ABGTZ:
8958b97a46SDavid du Colombier 	case ABLEZ:
9058b97a46SDavid du Colombier 	case ABLTZ:
9158b97a46SDavid du Colombier 	case ABLTZAL:
9258b97a46SDavid du Colombier 	case ABNE:
9358b97a46SDavid du Colombier 		return 1;
9458b97a46SDavid du Colombier 	}
9558b97a46SDavid du Colombier 	return 0;
9658b97a46SDavid du Colombier }
9758b97a46SDavid du Colombier 
9858b97a46SDavid du Colombier static int
isbranch(Prog * p)9958b97a46SDavid du Colombier isbranch(Prog *p)
10058b97a46SDavid du Colombier {
10158b97a46SDavid du Colombier 	if(p == nil)
10258b97a46SDavid du Colombier 		return 0;
10358b97a46SDavid du Colombier 	switch(p->as){
10458b97a46SDavid du Colombier 	case AJAL:
10558b97a46SDavid du Colombier 	case AJMP:
10658b97a46SDavid du Colombier 	case ARET:
10758b97a46SDavid du Colombier 	case ARFE:
10858b97a46SDavid du Colombier 		return 1;
10958b97a46SDavid du Colombier 	}
11058b97a46SDavid du Colombier 	if(iscondbranch(p))
11158b97a46SDavid du Colombier 		return 1;
11258b97a46SDavid du Colombier 	return 0;
11358b97a46SDavid du Colombier }
11458b97a46SDavid du Colombier 
115*0400b647SDavid du Colombier static void
nopafter(Prog * p)116*0400b647SDavid du Colombier nopafter(Prog *p)
117*0400b647SDavid du Colombier {
118*0400b647SDavid du Colombier 	p->mark |= LABEL|SYNC;
119*0400b647SDavid du Colombier 	addnop(p);
120*0400b647SDavid du Colombier }
121*0400b647SDavid du Colombier 
12258b97a46SDavid du Colombier /*
12358b97a46SDavid du Colombier  * workaround for 24k erratum #48, costs about 0.5% in space.
12458b97a46SDavid du Colombier  * inserts a NOP before the last of 3 consecutive stores.
12558b97a46SDavid du Colombier  * double-word stores complicate things.
12658b97a46SDavid du Colombier  */
12758b97a46SDavid du Colombier static int
no3stores(Prog * p)12858b97a46SDavid du Colombier no3stores(Prog *p)
12958b97a46SDavid du Colombier {
13058b97a46SDavid du Colombier 	Prog *p1;
13158b97a46SDavid du Colombier 
13258b97a46SDavid du Colombier 	if(!isstore(p))
13358b97a46SDavid du Colombier 		return 0;
13458b97a46SDavid du Colombier 	p1 = p->link;
13558b97a46SDavid du Colombier 	if(!isstore(p1))
13658b97a46SDavid du Colombier 		return 0;
13758b97a46SDavid du Colombier 	if(isdblwrdmov(p) || isdblwrdmov(p1)) {
138*0400b647SDavid du Colombier 		nopafter(p);
13958b97a46SDavid du Colombier 		nop.store.count++;
14058b97a46SDavid du Colombier 		nop.store.outof++;
14158b97a46SDavid du Colombier 		return 1;
14258b97a46SDavid du Colombier 	}
14358b97a46SDavid du Colombier 	if(isstore(p1->link)) {
144*0400b647SDavid du Colombier 		nopafter(p1);
14558b97a46SDavid du Colombier 		nop.store.count++;
14658b97a46SDavid du Colombier 		nop.store.outof++;
14758b97a46SDavid du Colombier 		return 1;
14858b97a46SDavid du Colombier 	}
14958b97a46SDavid du Colombier 	return 0;
15058b97a46SDavid du Colombier }
15158b97a46SDavid du Colombier 
15258b97a46SDavid du Colombier /*
15358b97a46SDavid du Colombier  * keep stores out of branch delay slots.
15458b97a46SDavid du Colombier  * this is costly in space (the other 9.5%), but makes no3stores effective.
15558b97a46SDavid du Colombier  * there is undoubtedly a better way to do this.
15658b97a46SDavid du Colombier  */
15758b97a46SDavid du Colombier void
storesnosched(void)15858b97a46SDavid du Colombier storesnosched(void)
15958b97a46SDavid du Colombier {
16058b97a46SDavid du Colombier 	Prog *p;
16158b97a46SDavid du Colombier 
16258b97a46SDavid du Colombier 	for(p = firstp; p != P; p = p->link)
16358b97a46SDavid du Colombier 		if(isstore(p))
164*0400b647SDavid du Colombier 			p->mark |= NOSCHED;
16558b97a46SDavid du Colombier }
16658b97a46SDavid du Colombier 
167*0400b647SDavid du Colombier int
triplestorenops(void)16858b97a46SDavid du Colombier triplestorenops(void)
16958b97a46SDavid du Colombier {
170*0400b647SDavid du Colombier 	int r;
17158b97a46SDavid du Colombier 	Prog *p, *p1;
17258b97a46SDavid du Colombier 
173*0400b647SDavid du Colombier 	r = 0;
17458b97a46SDavid du Colombier 	for(p = firstp; p != P; p = p1) {
17558b97a46SDavid du Colombier 		p1 = p->link;
17658b97a46SDavid du Colombier //		if (p->mark & NOSCHED)
17758b97a46SDavid du Colombier //			continue;
178*0400b647SDavid du Colombier 		if(ismove(p) && isstore(p)) {
179*0400b647SDavid du Colombier 			if (no3stores(p))
180*0400b647SDavid du Colombier 				r++;
181*0400b647SDavid du Colombier 			/*
182*0400b647SDavid du Colombier 			 * given storenosched, the next two
183*0400b647SDavid du Colombier 			 * checks shouldn't be necessary.
184*0400b647SDavid du Colombier 			 */
185*0400b647SDavid du Colombier 			/*
186*0400b647SDavid du Colombier 			 * add nop after first MOV in `MOV; Bcond; MOV'.
187*0400b647SDavid du Colombier 			 */
188*0400b647SDavid du Colombier 			else if(isbranch(p1) && isstore(p1->link)) {
189*0400b647SDavid du Colombier 				nopafter(p);
190*0400b647SDavid du Colombier 				nop.branch.count++;
191*0400b647SDavid du Colombier 				nop.branch.outof++;
192*0400b647SDavid du Colombier 				r++;
193*0400b647SDavid du Colombier 			}
194*0400b647SDavid du Colombier 			/*
195*0400b647SDavid du Colombier 			 * this may be a branch target, so insert a nop after,
196*0400b647SDavid du Colombier 			 * in case a branch leading here has a store in its
197*0400b647SDavid du Colombier 			 * delay slot and we have consecutive stores here.
198*0400b647SDavid du Colombier 			 */
199*0400b647SDavid du Colombier 			if(p->mark & (LABEL|SYNC) && !isnop(p1)) {
200*0400b647SDavid du Colombier 				nopafter(p);
201*0400b647SDavid du Colombier 				nop.branch.count++;
202*0400b647SDavid du Colombier 				nop.branch.outof++;
203*0400b647SDavid du Colombier 				r++;
204*0400b647SDavid du Colombier 			}
205*0400b647SDavid du Colombier 		} else if (isbranch(p))
20658b97a46SDavid du Colombier 			/*
20758b97a46SDavid du Colombier 			 * can't ignore delay slot of a conditional branch;
20858b97a46SDavid du Colombier 			 * the branch could fail and fall through.
20958b97a46SDavid du Colombier 			 */
21058b97a46SDavid du Colombier 			if (!iscondbranch(p) && p1)
21158b97a46SDavid du Colombier 				p1 = p1->link;	/* skip its delay slot */
21258b97a46SDavid du Colombier 	}
213*0400b647SDavid du Colombier 	return r;
21458b97a46SDavid du Colombier }
21558b97a46SDavid du Colombier 
2163e12c5d1SDavid du Colombier void
noops(void)2173e12c5d1SDavid du Colombier noops(void)
2183e12c5d1SDavid du Colombier {
219219b2ee8SDavid du Colombier 	Prog *p, *p1, *q, *q1;
220219b2ee8SDavid du Colombier 	int o, curframe, curbecome, maxbecome;
2213e12c5d1SDavid du Colombier 
2223e12c5d1SDavid du Colombier 	/*
223219b2ee8SDavid du Colombier 	 * find leaf subroutines
224219b2ee8SDavid du Colombier 	 * become sizes
225219b2ee8SDavid du Colombier 	 * frame sizes
226219b2ee8SDavid du Colombier 	 * strip NOPs
227219b2ee8SDavid du Colombier 	 * expand RET
228219b2ee8SDavid du Colombier 	 * expand BECOME pseudo
2293e12c5d1SDavid du Colombier 	 */
2303e12c5d1SDavid du Colombier 
2313e12c5d1SDavid du Colombier 	if(debug['v'])
2323e12c5d1SDavid du Colombier 		Bprint(&bso, "%5.2f noops\n", cputime());
2333e12c5d1SDavid du Colombier 	Bflush(&bso);
234219b2ee8SDavid du Colombier 
235219b2ee8SDavid du Colombier 	curframe = 0;
236219b2ee8SDavid du Colombier 	curbecome = 0;
237219b2ee8SDavid du Colombier 	maxbecome = 0;
238219b2ee8SDavid du Colombier 	curtext = 0;
2393e12c5d1SDavid du Colombier 
2403e12c5d1SDavid du Colombier 	q = P;
2413e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
2423e12c5d1SDavid du Colombier 
243219b2ee8SDavid du Colombier 		/* find out how much arg space is used in this TEXT */
244219b2ee8SDavid du Colombier 		if(p->to.type == D_OREG && p->to.reg == REGSP)
245219b2ee8SDavid du Colombier 			if(p->to.offset > curframe)
246219b2ee8SDavid du Colombier 				curframe = p->to.offset;
247219b2ee8SDavid du Colombier 
2483e12c5d1SDavid du Colombier 		switch(p->as) {
2493e12c5d1SDavid du Colombier 		case ATEXT:
250219b2ee8SDavid du Colombier 			if(curtext && curtext->from.sym) {
251219b2ee8SDavid du Colombier 				curtext->from.sym->frame = curframe;
252219b2ee8SDavid du Colombier 				curtext->from.sym->become = curbecome;
253219b2ee8SDavid du Colombier 				if(curbecome > maxbecome)
254219b2ee8SDavid du Colombier 					maxbecome = curbecome;
255219b2ee8SDavid du Colombier 			}
256219b2ee8SDavid du Colombier 			curframe = 0;
257219b2ee8SDavid du Colombier 			curbecome = 0;
258219b2ee8SDavid du Colombier 
259219b2ee8SDavid du Colombier 			p->mark |= LABEL|LEAF|SYNC;
2603e12c5d1SDavid du Colombier 			if(p->link)
2613e12c5d1SDavid du Colombier 				p->link->mark |= LABEL;
2623e12c5d1SDavid du Colombier 			curtext = p;
263219b2ee8SDavid du Colombier 			break;
2643e12c5d1SDavid du Colombier 
2653e12c5d1SDavid du Colombier 		/* too hard, just leave alone */
2663e12c5d1SDavid du Colombier 		case AMOVW:
267219b2ee8SDavid du Colombier 			if(p->to.type == D_FCREG ||
268219b2ee8SDavid du Colombier 			   p->to.type == D_MREG) {
269219b2ee8SDavid du Colombier 				p->mark |= LABEL|SYNC;
270219b2ee8SDavid du Colombier 				break;
2713e12c5d1SDavid du Colombier 			}
272219b2ee8SDavid du Colombier 			if(p->from.type == D_FCREG ||
273219b2ee8SDavid du Colombier 			   p->from.type == D_MREG) {
274219b2ee8SDavid du Colombier 				p->mark |= LABEL|SYNC;
275219b2ee8SDavid du Colombier 				addnop(p);
276219b2ee8SDavid du Colombier 				addnop(p);
277219b2ee8SDavid du Colombier 				nop.mfrom.count += 2;
278219b2ee8SDavid du Colombier 				nop.mfrom.outof += 2;
279219b2ee8SDavid du Colombier 				break;
280219b2ee8SDavid du Colombier 			}
281219b2ee8SDavid du Colombier 			break;
2823e12c5d1SDavid du Colombier 
2833e12c5d1SDavid du Colombier 		/* too hard, just leave alone */
2847dd7cddfSDavid du Colombier 		case ACASE:
2853e12c5d1SDavid du Colombier 		case ASYSCALL:
2863e12c5d1SDavid du Colombier 		case AWORD:
2873e12c5d1SDavid du Colombier 		case ATLBWR:
2883e12c5d1SDavid du Colombier 		case ATLBWI:
2893e12c5d1SDavid du Colombier 		case ATLBP:
2903e12c5d1SDavid du Colombier 		case ATLBR:
291219b2ee8SDavid du Colombier 			p->mark |= LABEL|SYNC;
2923e12c5d1SDavid du Colombier 			break;
293219b2ee8SDavid du Colombier 
294219b2ee8SDavid du Colombier 		case ANOR:
295219b2ee8SDavid du Colombier 			if(p->to.type == D_REG && p->to.reg == REGZERO)
296219b2ee8SDavid du Colombier 				p->mark |= LABEL|SYNC;
297219b2ee8SDavid du Colombier 			break;
2983e12c5d1SDavid du Colombier 
2993e12c5d1SDavid du Colombier 		case ARET:
300219b2ee8SDavid du Colombier 			/* special form of RET is BECOME */
301219b2ee8SDavid du Colombier 			if(p->from.type == D_CONST)
302219b2ee8SDavid du Colombier 				if(p->from.offset > curbecome)
303219b2ee8SDavid du Colombier 					curbecome = p->from.offset;
304219b2ee8SDavid du Colombier 
3053e12c5d1SDavid du Colombier 			if(p->link != P)
3063e12c5d1SDavid du Colombier 				p->link->mark |= LABEL;
307219b2ee8SDavid du Colombier 			break;
3083e12c5d1SDavid du Colombier 
3093e12c5d1SDavid du Colombier 		case ANOP:
3103e12c5d1SDavid du Colombier 			q1 = p->link;
3113e12c5d1SDavid du Colombier 			q->link = q1;		/* q is non-nop */
3123e12c5d1SDavid du Colombier 			q1->mark |= p->mark;
3133e12c5d1SDavid du Colombier 			continue;
3143e12c5d1SDavid du Colombier 
3157dd7cddfSDavid du Colombier 		case ABCASE:
3167dd7cddfSDavid du Colombier 			p->mark |= LABEL|SYNC;
3177dd7cddfSDavid du Colombier 			goto dstlab;
3187dd7cddfSDavid du Colombier 
3193e12c5d1SDavid du Colombier 		case ABGEZAL:
3203e12c5d1SDavid du Colombier 		case ABLTZAL:
3213e12c5d1SDavid du Colombier 		case AJAL:
3223e12c5d1SDavid du Colombier 			if(curtext != P)
3233e12c5d1SDavid du Colombier 				curtext->mark &= ~LEAF;
324219b2ee8SDavid du Colombier 
325219b2ee8SDavid du Colombier 		case AJMP:
3263e12c5d1SDavid du Colombier 		case ABEQ:
3273e12c5d1SDavid du Colombier 		case ABGEZ:
3283e12c5d1SDavid du Colombier 		case ABGTZ:
3293e12c5d1SDavid du Colombier 		case ABLEZ:
3303e12c5d1SDavid du Colombier 		case ABLTZ:
3313e12c5d1SDavid du Colombier 		case ABNE:
3323e12c5d1SDavid du Colombier 		case ABFPT:
3333e12c5d1SDavid du Colombier 		case ABFPF:
334219b2ee8SDavid du Colombier 			p->mark |= BRANCH;
3357dd7cddfSDavid du Colombier 
3367dd7cddfSDavid du Colombier 		dstlab:
3373e12c5d1SDavid du Colombier 			q1 = p->cond;
3383e12c5d1SDavid du Colombier 			if(q1 != P) {
3393e12c5d1SDavid du Colombier 				while(q1->as == ANOP) {
3403e12c5d1SDavid du Colombier 					q1 = q1->link;
3413e12c5d1SDavid du Colombier 					p->cond = q1;
3423e12c5d1SDavid du Colombier 				}
3433e12c5d1SDavid du Colombier 				if(!(q1->mark & LEAF))
3443e12c5d1SDavid du Colombier 					q1->mark |= LABEL;
3453e12c5d1SDavid du Colombier 			} else
3463e12c5d1SDavid du Colombier 				p->mark |= LABEL;
3473e12c5d1SDavid du Colombier 			q1 = p->link;
3483e12c5d1SDavid du Colombier 			if(q1 != P)
3493e12c5d1SDavid du Colombier 				q1->mark |= LABEL;
350219b2ee8SDavid du Colombier 			break;
351219b2ee8SDavid du Colombier 		}
3523e12c5d1SDavid du Colombier 		q = p;
353219b2ee8SDavid du Colombier 	}
354219b2ee8SDavid du Colombier 
355219b2ee8SDavid du Colombier 	if(curtext && curtext->from.sym) {
356219b2ee8SDavid du Colombier 		curtext->from.sym->frame = curframe;
357219b2ee8SDavid du Colombier 		curtext->from.sym->become = curbecome;
358219b2ee8SDavid du Colombier 		if(curbecome > maxbecome)
359219b2ee8SDavid du Colombier 			maxbecome = curbecome;
360219b2ee8SDavid du Colombier 	}
361219b2ee8SDavid du Colombier 
362219b2ee8SDavid du Colombier 	if(debug['b'])
363219b2ee8SDavid du Colombier 		print("max become = %d\n", maxbecome);
364219b2ee8SDavid du Colombier 	xdefine("ALEFbecome", STEXT, maxbecome);
365219b2ee8SDavid du Colombier 
366219b2ee8SDavid du Colombier 	curtext = 0;
367219b2ee8SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
368219b2ee8SDavid du Colombier 		switch(p->as) {
369219b2ee8SDavid du Colombier 		case ATEXT:
370219b2ee8SDavid du Colombier 			curtext = p;
371219b2ee8SDavid du Colombier 			break;
372219b2ee8SDavid du Colombier 		case AJAL:
373219b2ee8SDavid du Colombier 			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
374219b2ee8SDavid du Colombier 				o = maxbecome - curtext->from.sym->frame;
375219b2ee8SDavid du Colombier 				if(o <= 0)
376219b2ee8SDavid du Colombier 					break;
377219b2ee8SDavid du Colombier 				/* calling a become or calling a variable */
378219b2ee8SDavid du Colombier 				if(p->to.sym == S || p->to.sym->become) {
379219b2ee8SDavid du Colombier 					curtext->to.offset += o;
380219b2ee8SDavid du Colombier 					if(debug['b']) {
381219b2ee8SDavid du Colombier 						curp = p;
382219b2ee8SDavid du Colombier 						print("%D calling %D increase %d\n",
383219b2ee8SDavid du Colombier 							&curtext->from, &p->to, o);
384219b2ee8SDavid du Colombier 					}
385219b2ee8SDavid du Colombier 				}
386219b2ee8SDavid du Colombier 			}
387219b2ee8SDavid du Colombier 			break;
3883e12c5d1SDavid du Colombier 		}
3893e12c5d1SDavid du Colombier 	}
3903e12c5d1SDavid du Colombier 
391219b2ee8SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
392219b2ee8SDavid du Colombier 		o = p->as;
393219b2ee8SDavid du Colombier 		switch(o) {
3943e12c5d1SDavid du Colombier 		case ATEXT:
3953e12c5d1SDavid du Colombier 			curtext = p;
3963e12c5d1SDavid du Colombier 			autosize = p->to.offset + 4;
3973e12c5d1SDavid du Colombier 			if(autosize <= 4)
3983e12c5d1SDavid du Colombier 			if(curtext->mark & LEAF) {
3993e12c5d1SDavid du Colombier 				p->to.offset = -4;
4003e12c5d1SDavid du Colombier 				autosize = 0;
4013e12c5d1SDavid du Colombier 			}
4023e12c5d1SDavid du Colombier 
4033e12c5d1SDavid du Colombier 			q = p;
4043e12c5d1SDavid du Colombier 			if(autosize) {
4053e12c5d1SDavid du Colombier 				q = prg();
4063e12c5d1SDavid du Colombier 				q->as = AADD;
4073e12c5d1SDavid du Colombier 				q->line = p->line;
4083e12c5d1SDavid du Colombier 				q->from.type = D_CONST;
4093e12c5d1SDavid du Colombier 				q->from.offset = -autosize;
4103e12c5d1SDavid du Colombier 				q->to.type = D_REG;
4113e12c5d1SDavid du Colombier 				q->to.reg = REGSP;
4123e12c5d1SDavid du Colombier 
4133e12c5d1SDavid du Colombier 				q->link = p->link;
4143e12c5d1SDavid du Colombier 				p->link = q;
4153e12c5d1SDavid du Colombier 			} else
4163e12c5d1SDavid du Colombier 			if(!(curtext->mark & LEAF)) {
4173e12c5d1SDavid du Colombier 				if(debug['v'])
4183e12c5d1SDavid du Colombier 					Bprint(&bso, "save suppressed in: %s\n",
4193e12c5d1SDavid du Colombier 						curtext->from.sym->name);
4203e12c5d1SDavid du Colombier 				Bflush(&bso);
4213e12c5d1SDavid du Colombier 				curtext->mark |= LEAF;
4223e12c5d1SDavid du Colombier 			}
4233e12c5d1SDavid du Colombier 
4243e12c5d1SDavid du Colombier 			if(curtext->mark & LEAF) {
4253e12c5d1SDavid du Colombier 				if(curtext->from.sym)
4263e12c5d1SDavid du Colombier 					curtext->from.sym->type = SLEAF;
4273e12c5d1SDavid du Colombier 				break;
4283e12c5d1SDavid du Colombier 			}
4293e12c5d1SDavid du Colombier 
4303e12c5d1SDavid du Colombier 			q1 = prg();
4313e12c5d1SDavid du Colombier 			q1->as = AMOVW;
4323e12c5d1SDavid du Colombier 			q1->line = p->line;
4333e12c5d1SDavid du Colombier 			q1->from.type = D_REG;
4343e12c5d1SDavid du Colombier 			q1->from.reg = REGLINK;
4353e12c5d1SDavid du Colombier 			q1->to.type = D_OREG;
4363e12c5d1SDavid du Colombier 			q1->from.offset = 0;
4373e12c5d1SDavid du Colombier 			q1->to.reg = REGSP;
4383e12c5d1SDavid du Colombier 
4393e12c5d1SDavid du Colombier 			q1->link = q->link;
4403e12c5d1SDavid du Colombier 			q->link = q1;
4413e12c5d1SDavid du Colombier 			break;
4423e12c5d1SDavid du Colombier 
4433e12c5d1SDavid du Colombier 		case ARET:
4443e12c5d1SDavid du Colombier 			nocache(p);
445219b2ee8SDavid du Colombier 			if(p->from.type == D_CONST)
446219b2ee8SDavid du Colombier 				goto become;
4473e12c5d1SDavid du Colombier 			if(curtext->mark & LEAF) {
4483e12c5d1SDavid du Colombier 				if(!autosize) {
4493e12c5d1SDavid du Colombier 					p->as = AJMP;
4503e12c5d1SDavid du Colombier 					p->from = zprg.from;
4513e12c5d1SDavid du Colombier 					p->to.type = D_OREG;
4523e12c5d1SDavid du Colombier 					p->to.offset = 0;
4533e12c5d1SDavid du Colombier 					p->to.reg = REGLINK;
454219b2ee8SDavid du Colombier 					p->mark |= BRANCH;
455219b2ee8SDavid du Colombier 					break;
4563e12c5d1SDavid du Colombier 				}
4573e12c5d1SDavid du Colombier 
4583e12c5d1SDavid du Colombier 				p->as = AADD;
4593e12c5d1SDavid du Colombier 				p->from.type = D_CONST;
4603e12c5d1SDavid du Colombier 				p->from.offset = autosize;
4613e12c5d1SDavid du Colombier 				p->to.type = D_REG;
4623e12c5d1SDavid du Colombier 				p->to.reg = REGSP;
4633e12c5d1SDavid du Colombier 
4643e12c5d1SDavid du Colombier 				q = prg();
4653e12c5d1SDavid du Colombier 				q->as = AJMP;
4663e12c5d1SDavid du Colombier 				q->line = p->line;
4673e12c5d1SDavid du Colombier 				q->to.type = D_OREG;
4683e12c5d1SDavid du Colombier 				q->to.offset = 0;
4693e12c5d1SDavid du Colombier 				q->to.reg = REGLINK;
470219b2ee8SDavid du Colombier 				q->mark |= BRANCH;
4713e12c5d1SDavid du Colombier 
4723e12c5d1SDavid du Colombier 				q->link = p->link;
4733e12c5d1SDavid du Colombier 				p->link = q;
474219b2ee8SDavid du Colombier 				break;
4753e12c5d1SDavid du Colombier 			}
4763e12c5d1SDavid du Colombier 			p->as = AMOVW;
4773e12c5d1SDavid du Colombier 			p->from.type = D_OREG;
4783e12c5d1SDavid du Colombier 			p->from.offset = 0;
4793e12c5d1SDavid du Colombier 			p->from.reg = REGSP;
4803e12c5d1SDavid du Colombier 			p->to.type = D_REG;
4813e12c5d1SDavid du Colombier 			p->to.reg = 2;
4823e12c5d1SDavid du Colombier 
4833e12c5d1SDavid du Colombier 			q = p;
4843e12c5d1SDavid du Colombier 			if(autosize) {
4853e12c5d1SDavid du Colombier 				q = prg();
4863e12c5d1SDavid du Colombier 				q->as = AADD;
4873e12c5d1SDavid du Colombier 				q->line = p->line;
4883e12c5d1SDavid du Colombier 				q->from.type = D_CONST;
4893e12c5d1SDavid du Colombier 				q->from.offset = autosize;
4903e12c5d1SDavid du Colombier 				q->to.type = D_REG;
4913e12c5d1SDavid du Colombier 				q->to.reg = REGSP;
4923e12c5d1SDavid du Colombier 
4933e12c5d1SDavid du Colombier 				q->link = p->link;
4943e12c5d1SDavid du Colombier 				p->link = q;
4953e12c5d1SDavid du Colombier 			}
4963e12c5d1SDavid du Colombier 
4973e12c5d1SDavid du Colombier 			q1 = prg();
4983e12c5d1SDavid du Colombier 			q1->as = AJMP;
4993e12c5d1SDavid du Colombier 			q1->line = p->line;
5003e12c5d1SDavid du Colombier 			q1->to.type = D_OREG;
5013e12c5d1SDavid du Colombier 			q1->to.offset = 0;
5023e12c5d1SDavid du Colombier 			q1->to.reg = 2;
503219b2ee8SDavid du Colombier 			q1->mark |= BRANCH;
5043e12c5d1SDavid du Colombier 
5053e12c5d1SDavid du Colombier 			q1->link = q->link;
5063e12c5d1SDavid du Colombier 			q->link = q1;
5073e12c5d1SDavid du Colombier 			break;
5083e12c5d1SDavid du Colombier 
509219b2ee8SDavid du Colombier 		become:
510219b2ee8SDavid du Colombier 			if(curtext->mark & LEAF) {
5113e12c5d1SDavid du Colombier 
512219b2ee8SDavid du Colombier 				q = prg();
513219b2ee8SDavid du Colombier 				q->line = p->line;
514219b2ee8SDavid du Colombier 				q->as = AJMP;
515219b2ee8SDavid du Colombier 				q->from = zprg.from;
516219b2ee8SDavid du Colombier 				q->to = p->to;
517219b2ee8SDavid du Colombier 				q->cond = p->cond;
518219b2ee8SDavid du Colombier 				q->link = p->link;
519219b2ee8SDavid du Colombier 				q->mark |= BRANCH;
520219b2ee8SDavid du Colombier 				p->link = q;
521219b2ee8SDavid du Colombier 
522219b2ee8SDavid du Colombier 				p->as = AADD;
523219b2ee8SDavid du Colombier 				p->from = zprg.from;
524219b2ee8SDavid du Colombier 				p->from.type = D_CONST;
525219b2ee8SDavid du Colombier 				p->from.offset = autosize;
526219b2ee8SDavid du Colombier 				p->to = zprg.to;
527219b2ee8SDavid du Colombier 				p->to.type = D_REG;
528219b2ee8SDavid du Colombier 				p->to.reg = REGSP;
529219b2ee8SDavid du Colombier 
530219b2ee8SDavid du Colombier 				break;
531219b2ee8SDavid du Colombier 			}
532219b2ee8SDavid du Colombier 			q = prg();
533219b2ee8SDavid du Colombier 			q->line = p->line;
534219b2ee8SDavid du Colombier 			q->as = AJMP;
535219b2ee8SDavid du Colombier 			q->from = zprg.from;
536219b2ee8SDavid du Colombier 			q->to = p->to;
537219b2ee8SDavid du Colombier 			q->cond = p->cond;
538219b2ee8SDavid du Colombier 			q->link = p->link;
539219b2ee8SDavid du Colombier 			q->mark |= BRANCH;
540219b2ee8SDavid du Colombier 			p->link = q;
541219b2ee8SDavid du Colombier 
542219b2ee8SDavid du Colombier 			q = prg();
543219b2ee8SDavid du Colombier 			q->line = p->line;
544219b2ee8SDavid du Colombier 			q->as = AADD;
545219b2ee8SDavid du Colombier 			q->from.type = D_CONST;
546219b2ee8SDavid du Colombier 			q->from.offset = autosize;
547219b2ee8SDavid du Colombier 			q->to.type = D_REG;
548219b2ee8SDavid du Colombier 			q->to.reg = REGSP;
549219b2ee8SDavid du Colombier 			q->link = p->link;
550219b2ee8SDavid du Colombier 			p->link = q;
551219b2ee8SDavid du Colombier 
552219b2ee8SDavid du Colombier 			p->as = AMOVW;
553219b2ee8SDavid du Colombier 			p->from = zprg.from;
554219b2ee8SDavid du Colombier 			p->from.type = D_OREG;
555219b2ee8SDavid du Colombier 			p->from.offset = 0;
556219b2ee8SDavid du Colombier 			p->from.reg = REGSP;
557219b2ee8SDavid du Colombier 			p->to = zprg.to;
558219b2ee8SDavid du Colombier 			p->to.type = D_REG;
559219b2ee8SDavid du Colombier 			p->to.reg = REGLINK;
560219b2ee8SDavid du Colombier 
5613e12c5d1SDavid du Colombier 			break;
5623e12c5d1SDavid du Colombier 		}
5633e12c5d1SDavid du Colombier 	}
56458b97a46SDavid du Colombier 	if (Mips24k)
56558b97a46SDavid du Colombier 		storesnosched();
5663e12c5d1SDavid du Colombier 
567219b2ee8SDavid du Colombier 	curtext = P;
568219b2ee8SDavid du Colombier 	q = P;		/* p - 1 */
569219b2ee8SDavid du Colombier 	q1 = firstp;	/* top of block */
570219b2ee8SDavid du Colombier 	o = 0;		/* count of instructions */
571219b2ee8SDavid du Colombier 	for(p = firstp; p != P; p = p1) {
572219b2ee8SDavid du Colombier 		p1 = p->link;
573219b2ee8SDavid du Colombier 		o++;
574219b2ee8SDavid du Colombier 		if(p->mark & NOSCHED){
575219b2ee8SDavid du Colombier 			if(q1 != p){
576219b2ee8SDavid du Colombier 				sched(q1, q);
5773e12c5d1SDavid du Colombier 			}
578219b2ee8SDavid du Colombier 			for(; p != P; p = p->link){
579219b2ee8SDavid du Colombier 				if(!(p->mark & NOSCHED))
580219b2ee8SDavid du Colombier 					break;
581219b2ee8SDavid du Colombier 				q = p;
5823e12c5d1SDavid du Colombier 			}
583219b2ee8SDavid du Colombier 			p1 = p;
584219b2ee8SDavid du Colombier 			q1 = p;
585219b2ee8SDavid du Colombier 			o = 0;
5863e12c5d1SDavid du Colombier 			continue;
5873e12c5d1SDavid du Colombier 		}
588219b2ee8SDavid du Colombier 		if(p->mark & (LABEL|SYNC)) {
589219b2ee8SDavid du Colombier 			if(q1 != p)
590219b2ee8SDavid du Colombier 				sched(q1, q);
591219b2ee8SDavid du Colombier 			q1 = p;
592219b2ee8SDavid du Colombier 			o = 1;
5933e12c5d1SDavid du Colombier 		}
594219b2ee8SDavid du Colombier 		if(p->mark & (BRANCH|SYNC)) {
595219b2ee8SDavid du Colombier 			sched(q1, p);
596219b2ee8SDavid du Colombier 			q1 = p1;
597219b2ee8SDavid du Colombier 			o = 0;
5983e12c5d1SDavid du Colombier 		}
599219b2ee8SDavid du Colombier 		if(o >= NSCHED) {
600219b2ee8SDavid du Colombier 			sched(q1, p);
601219b2ee8SDavid du Colombier 			q1 = p1;
602219b2ee8SDavid du Colombier 			o = 0;
6033e12c5d1SDavid du Colombier 		}
604219b2ee8SDavid du Colombier 		q = p;
6053e12c5d1SDavid du Colombier 	}
60658b97a46SDavid du Colombier 
60758b97a46SDavid du Colombier 	if (Mips24k)
60858b97a46SDavid du Colombier 		triplestorenops();
6093e12c5d1SDavid du Colombier }
6103e12c5d1SDavid du Colombier 
6113e12c5d1SDavid du Colombier void
addnop(Prog * p)6123e12c5d1SDavid du Colombier addnop(Prog *p)
6133e12c5d1SDavid du Colombier {
6143e12c5d1SDavid du Colombier 	Prog *q;
6153e12c5d1SDavid du Colombier 
6163e12c5d1SDavid du Colombier 	q = prg();
6173e12c5d1SDavid du Colombier 	q->as = ANOR;
6183e12c5d1SDavid du Colombier 	q->line = p->line;
6193e12c5d1SDavid du Colombier 	q->from.type = D_REG;
6203e12c5d1SDavid du Colombier 	q->from.reg = REGZERO;
6213e12c5d1SDavid du Colombier 	q->to.type = D_REG;
6223e12c5d1SDavid du Colombier 	q->to.reg = REGZERO;
6233e12c5d1SDavid du Colombier 
6243e12c5d1SDavid du Colombier 	q->link = p->link;
6253e12c5d1SDavid du Colombier 	p->link = q;
6263e12c5d1SDavid du Colombier }
6273e12c5d1SDavid du Colombier 
6283e12c5d1SDavid du Colombier void
nocache(Prog * p)629219b2ee8SDavid du Colombier nocache(Prog *p)
6303e12c5d1SDavid du Colombier {
631219b2ee8SDavid du Colombier 	p->optab = 0;
632219b2ee8SDavid du Colombier 	p->from.class = 0;
633219b2ee8SDavid du Colombier 	p->to.class = 0;
6343e12c5d1SDavid du Colombier }
635