Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include        "l.h"

void
noops(void)
{
        Prog *p, *p1, *q, *q1;
        int o, mov, aoffset, curframe, curbecome, maxbecome;

        /*
         * find leaf subroutines
         * become sizes
         * frame sizes
         * strip NOPs
         * expand RET
         * expand BECOME pseudo
         */

        if(debug['v'])
                Bprint(&bso, "%5.2f noops\n", cputime());
        Bflush(&bso);

        curframe = 0;
        curbecome = 0;
        maxbecome = 0;
        curtext = 0;
        q = P;
        for(p = firstp; p != P; p = p->link) {

                /* find out how much arg space is used in this TEXT */
                if(p->to.type == D_OREG && p->to.reg == REGSP)
                        if(p->to.offset > curframe)
                                curframe = p->to.offset;

                switch(p->as) {
                /* too hard, just leave alone */
                case ATEXT:
                        if(curtext && curtext->from.sym) {
                                curtext->from.sym->frame = curframe;
                                curtext->from.sym->become = curbecome;
                                if(curbecome > maxbecome)
                                        maxbecome = curbecome;
                        }
                        curframe = 0;
                        curbecome = 0;

                        q = p;
                        p->mark |= LABEL|LEAF|SYNC;
                        if(p->link)
                                p->link->mark |= LABEL;
                        curtext = p;
                        break;

                case ANOR:
                        q = p;
                        if(p->to.type == D_REG)
                                if(p->to.reg == REGZERO)
                                        p->mark |= LABEL|SYNC;
                        break;

                case ALWAR:
                case ASTWCCC:
                case AECIWX:
                case AECOWX:
                case AEIEIO:
                case AICBI:
                case AISYNC:
                case ATLBIE:
                case ADCBF:
                case ADCBI:
                case ADCBST:
                case ADCBT:
                case ADCBTST:
                case ADCBZ:
                case ASYNC:
                case ATW:
                case AWORD:
                case ARFI:
                case ARFCI:
                        q = p;
                        p->mark |= LABEL|SYNC;
                        continue;

                case AMOVW:
                        q = p;
                        switch(p->from.type) {
                        case D_MSR:
                        case D_SREG:
                        case D_SPR:
                        case D_FPSCR:
                        case D_CREG:
                        case D_DCR:
                                p->mark |= LABEL|SYNC;
                        }
                        switch(p->to.type) {
                        case D_MSR:
                        case D_SREG:
                        case D_SPR:
                        case D_FPSCR:
                        case D_CREG:
                        case D_DCR:
                                p->mark |= LABEL|SYNC;
                        }
                        continue;

                case AFABS:
                case AFABSCC:
                case AFADD:
                case AFADDCC:
                case AFCTIW:
                case AFCTIWCC:
                case AFCTIWZ:
                case AFCTIWZCC:
                case AFDIV:
                case AFDIVCC:
                case AFMADD:
                case AFMADDCC:
                case AFMOVD:
                case AFMOVDU:
                /* case AFMOVDS: */
                case AFMOVS:
                case AFMOVSU:
                /* case AFMOVSD: */
                case AFMSUB:
                case AFMSUBCC:
                case AFMUL:
                case AFMULCC:
                case AFNABS:
                case AFNABSCC:
                case AFNEG:
                case AFNEGCC:
                case AFNMADD:
                case AFNMADDCC:
                case AFNMSUB:
                case AFNMSUBCC:
                case AFRSP:
                case AFRSPCC:
                case AFSUB:
                case AFSUBCC:
                        q = p;
                        p->mark |= FLOAT;
                        continue;

                case ABL:
                case ABCL:
                        if(curtext != P)
                                curtext->mark &= ~LEAF;

                case ABC:
                case ABEQ:
                case ABGE:
                case ABGT:
                case ABLE:
                case ABLT:
                case ABNE:
                case ABR:
                case ABVC:
                case ABVS:

                        p->mark |= BRANCH;
                        q = p;
                        q1 = p->cond;
                        if(q1 != P) {
                                while(q1->as == ANOP) {
                                        q1 = q1->link;
                                        p->cond = q1;
                                }
                                if(!(q1->mark & LEAF))
                                        q1->mark |= LABEL;
                        } else
                                p->mark |= LABEL;
                        q1 = p->link;
                        if(q1 != P)
                                q1->mark |= LABEL;
                        continue;

                case AFCMPO:
                case AFCMPU:
                        q = p;
                        p->mark |= FCMP|FLOAT;
                        continue;

                case ARETURN:
                        /* special form of RETURN is BECOME */
                        if(p->from.type == D_CONST)
                                if(p->from.offset > curbecome)
                                        curbecome = p->from.offset;

                        q = p;
                        if(p->link != P)
                                p->link->mark |= LABEL;
                        continue;

                case ANOP:
                        q1 = p->link;
                        q->link = q1;           /* q is non-nop */
                        q1->mark |= p->mark;
                        continue;

                default:
                        q = p;
                        continue;
                }
        }
        if(curtext && curtext->from.sym) {
                curtext->from.sym->frame = curframe;
                curtext->from.sym->become = curbecome;
                if(curbecome > maxbecome)
                        maxbecome = curbecome;
        }

        if(debug['b'])
                print("max become = %d\n", maxbecome);
        xdefine("ALEFbecome", STEXT, maxbecome);

        curtext = 0;
        for(p = firstp; p != P; p = p->link) {
                switch(p->as) {
                case ATEXT:
                        curtext = p;
                        break;

                case ABL:       /* ABCL? */
                        if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
                                o = maxbecome - curtext->from.sym->frame;
                                if(o <= 0)
                                        break;
                                /* calling a become or calling a variable */
                                if(p->to.sym == S || p->to.sym->become) {
                                        curtext->to.offset += o;
                                        if(debug['b']) {
                                                curp = p;
                                                print("%D calling %D increase %d\n",
                                                        &curtext->from, &p->to, o);
                                        }
                                }
                        }
                        break;
                }
        }

        curtext = P;
        for(p = firstp; p != P; p = p->link) {
                o = p->as;
                switch(o) {
                case ATEXT:
                        mov = AMOVW;
                        aoffset = 0;
                        curtext = p;
                        autosize = p->to.offset + 4;
                        if((p->mark & LEAF) && autosize <= 4)
                                autosize = 0;
                        else
                                if(autosize & 4)
                                        autosize += 4;
                        p->to.offset = autosize - 4;

                        q = p;
                        if(autosize) {
                                /* use MOVWU to adjust R1 when saving R31, if autosize is small */
                                if(!(curtext->mark & LEAF) && autosize >= -BIG && autosize <= BIG) {
                                        mov = AMOVWU;
                                        aoffset = -autosize;
                                } else {
                                        q = prg();
                                        q->as = AADD;
                                        q->line = p->line;
                                        q->from.type = D_CONST;
                                        q->from.offset = -autosize;
                                        q->to.type = D_REG;
                                        q->to.reg = REGSP;

                                        q->link = p->link;
                                        p->link = q;
                                }
                        } else
                        if(!(curtext->mark & LEAF)) {
                                if(debug['v'])
                                        Bprint(&bso, "save suppressed in: %s\n",
                                                curtext->from.sym->name);
                                curtext->mark |= LEAF;
                        }

                        if(curtext->mark & LEAF) {
                                if(curtext->from.sym)
                                        curtext->from.sym->type = SLEAF;
                                break;
                        }

                        q1 = prg();
                        q1->as = mov;
                        q1->line = p->line;
                        q1->from.type = D_REG;
                        q1->from.reg = REGTMP;
                        q1->to.type = D_OREG;
                        q1->to.offset = aoffset;
                        q1->to.reg = REGSP;

                        q1->link = q->link;
                        q->link = q1;

                        q1 = prg();
                        q1->as = AMOVW;
                        q1->line = p->line;
                        q1->from.type = D_SPR;
                        q1->from.offset = D_LR;
                        q1->to.type = D_REG;
                        q1->to.reg = REGTMP;

                        q1->link = q->link;
                        q->link = q1;
                        break;

                case ARETURN:
                        if(p->from.type == D_CONST)
                                goto become;
                        if(curtext->mark & LEAF) {
                                if(!autosize) {
                                        p->as = ABR;
                                        p->from = zprg.from;
                                        p->to.type = D_SPR;
                                        p->to.offset = D_LR;
                                        p->mark |= BRANCH;
                                        break;
                                }

                                p->as = AADD;
                                p->from.type = D_CONST;
                                p->from.offset = autosize;
                                p->to.type = D_REG;
                                p->to.reg = REGSP;

                                q = prg();
                                q->as = ABR;
                                q->line = p->line;
                                q->to.type = D_SPR;
                                q->to.offset = D_LR;
                                q->mark |= BRANCH;

                                q->link = p->link;
                                p->link = q;
                                break;
                        }

                        p->as = AMOVW;
                        p->from.type = D_OREG;
                        p->from.offset = 0;
                        p->from.reg = REGSP;
                        p->to.type = D_REG;
                        p->to.reg = REGTMP;

                        q = prg();
                        q->as = AMOVW;
                        q->line = p->line;
                        q->from.type = D_REG;
                        q->from.reg = REGTMP;
                        q->to.type = D_SPR;
                        q->to.offset = D_LR;

                        q->link = p->link;
                        p->link = q;
                        p = q;

                        if(autosize) {
                                q = prg();
                                q->as = AADD;
                                q->line = p->line;
                                q->from.type = D_CONST;
                                q->from.offset = autosize;
                                q->to.type = D_REG;
                                q->to.reg = REGSP;

                                q->link = p->link;
                                p->link = q;
                        }

                        q1 = prg();
                        q1->as = ABR;
                        q1->line = p->line;
                        q1->to.type = D_SPR;
                        q1->to.offset = D_LR;
                        q1->mark |= BRANCH;

                        q1->link = q->link;
                        q->link = q1;
                        break;

                become:
                        if(curtext->mark & LEAF) {

                                q = prg();
                                q->line = p->line;
                                q->as = ABR;
                                q->from = zprg.from;
                                q->to = p->to;
                                q->cond = p->cond;
                                q->link = p->link;
                                q->mark |= BRANCH;
                                p->link = q;

                                p->as = AADD;
                                p->from = zprg.from;
                                p->from.type = D_CONST;
                                p->from.offset = autosize;
                                p->to = zprg.to;
                                p->to.type = D_REG;
                                p->to.reg = REGSP;

                                break;
                        }
                        q = prg();
                        q->line = p->line;
                        q->as = ABR;
                        q->from = zprg.from;
                        q->to = p->to;
                        q->cond = p->cond;
                        q->mark |= BRANCH;
                        q->link = p->link;
                        p->link = q;

                        q = prg();
                        q->line = p->line;
                        q->as = AADD;
                        q->from.type = D_CONST;
                        q->from.offset = autosize;
                        q->to.type = D_REG;
                        q->to.reg = REGSP;
                        q->link = p->link;
                        p->link = q;

                        q = prg();
                        q->line = p->line;
                        q->as = AMOVW;
                        q->line = p->line;
                        q->from.type = D_REG;
                        q->from.reg = REGTMP;
                        q->to.type = D_SPR;
                        q->to.offset = D_LR;
                        q->link = p->link;
                        p->link = q;

                        p->as = AMOVW;
                        p->from = zprg.from;
                        p->from.type = D_OREG;
                        p->from.offset = 0;
                        p->from.reg = REGSP;
                        p->to = zprg.to;
                        p->to.type = D_REG;
                        p->to.reg = REGTMP;

                        break;
                }
        }

        if(debug['Q'] == 0)
                return;

        curtext = P;
        q = P;          /* p - 1 */
        q1 = firstp;    /* top of block */
        o = 0;          /* count of instructions */
        for(p = firstp; p != P; p = p1) {
                p1 = p->link;
                o++;
                if(p->mark & NOSCHED){
                        if(q1 != p){
                                sched(q1, q);
                        }
                        for(; p != P; p = p->link){
                                if(!(p->mark & NOSCHED))
                                        break;
                                q = p;
                        }
                        p1 = p;
                        q1 = p;
                        o = 0;
                        continue;
                }
                if(p->mark & (LABEL|SYNC)) {
                        if(q1 != p)
                                sched(q1, q);
                        q1 = p;
                        o = 1;
                }
                if(p->mark & (BRANCH|SYNC)) {
                        sched(q1, p);
                        q1 = p1;
                        o = 0;
                }
                if(o >= NSCHED) {
                        sched(q1, p);
                        q1 = p1;
                        o = 0;
                }
                q = p;
        }
}

void
addnop(Prog *p)
{
        Prog *q;

        q = prg();
        q->as = ANOR;
        q->line = p->line;
        q->from.type = D_REG;
        q->from.reg = REGZERO;
        q->to.type = D_REG;
        q->to.reg = REGZERO;

        q->link = p->link;
        p->link = q;
}