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