Subversion Repositories planix.SVN

Rev

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

#include        "l.h"

void
span(void)
{
        Prog *p;
        Sym *setext;
        Optab *o;
        int m;
        long c;

        if(debug['v'])
                Bprint(&bso, "%5.2f span\n", cputime());
        Bflush(&bso);
        c = INITTEXT;
        for(p = firstp; p != P; p = p->link) {
                p->pc = c;
                o = oplook(p);
                m = o->size;
                if(m == 0) {
                        if(p->as == ATEXT) {
                                curtext = p;
                                autosize = p->to.offset + 4;
                                if(p->from.sym != S)
                                        p->from.sym->value = c;
                                continue;
                        }
                        if(p->as != ANOP)
                                diag("zero-width instruction\n%P", p);
                        continue;
                }
                c += m;
        }
        c = rnd(c, 8);

        setext = lookup("etext", 0);
        if(setext != S) {
                setext->value = c;
                textsize = c - INITTEXT;
        }
        if(INITRND)
                INITDAT = rnd(c, INITRND);
        if(debug['v'])
                Bprint(&bso, "tsize = %lux\n", textsize);
        Bflush(&bso);
}
                
void
xdefine(char *p, int t, long v)
{
        Sym *s;

        s = lookup(p, 0);
        if(s->type == 0 || s->type == SXREF) {
                s->type = t;
                s->value = v;
        }
}

long
regoff(Adr *a)
{

        instoffset = 0;
        aclass(a);
        return instoffset;
}

int
aclass(Adr *a)
{
        Sym *s;
        int t;

        switch(a->type) {
        case D_NONE:
                return C_NONE;

        case D_REG:
                return C_REG;

        case D_FREG:
                return C_FREG;

        case D_CREG:
                return C_CREG;

        case D_PREG:
                if(a->reg == D_FSR)
                        return C_FSR;
                if(a->reg == D_FPQ)
                        return C_FQ;
                return C_PREG;

        case D_OREG:
                switch(a->name) {
                case D_EXTERN:
                case D_STATIC:
                        if(a->sym == S)
                                break;
                        t = a->sym->type;
                        if(t == 0 || t == SXREF) {
                                diag("undefined external: %s in %s",
                                        a->sym->name, TNAME);
                                a->sym->type = SDATA;
                        }
                        instoffset = a->sym->value + a->offset - BIG;
                        if(instoffset >= -BIG && instoffset < BIG) {
                                if(instoffset & 7)
                                        return C_OSEXT;
                                return C_ESEXT;
                        }
                        if(instoffset & 7)
                                return C_OLEXT;
                        return C_ELEXT;
                case D_AUTO:
                        instoffset = autosize + a->offset;
                        goto dauto;

                case D_PARAM:
                        instoffset = autosize + a->offset + 4L;
                dauto:
                        if(instoffset >= -BIG && instoffset < BIG) {
                                if(instoffset & 7)
                                        return C_OSAUTO;
                                return C_ESAUTO;
                        }
                        if(instoffset & 7)
                                return C_OLAUTO;
                        return C_ELAUTO;
                case D_NONE:
                        instoffset = a->offset;
                        if(instoffset == 0)
                                return C_ZOREG;
                        if(instoffset >= -BIG && instoffset < BIG)
                                return C_SOREG;
                        return C_LOREG;
                }
                return C_GOK;

        case D_ASI:
                if(a->name == D_NONE)
                        return C_ASI;
                return C_GOK;

        case D_CONST:
                switch(a->name) {

                case D_NONE:
                        instoffset = a->offset;
                consize:
                        if(instoffset == 0)
                                return C_ZCON;
                        if(instoffset >= -0x1000 && instoffset <= 0xfff)
                                return C_SCON;
                        if((instoffset & 0x3ff) == 0)
                                return C_UCON;
                        return C_LCON;

                case D_EXTERN:
                case D_STATIC:
                        s = a->sym;
                        if(s == S)
                                break;
                        t = s->type;
                        if(t == 0 || t == SXREF) {
                                diag("undefined external: %s in %s",
                                        s->name, TNAME);
                                s->type = SDATA;
                        }
                        if(s->type == STEXT || s->type == SLEAF) {
                                instoffset = s->value + a->offset;
                                return C_LCON;
                        }
                        if(s->type == SCONST) {
                                instoffset = s->value + a->offset;
                                goto consize;
                        }
                        instoffset = s->value + a->offset - BIG;
                        if(instoffset >= -BIG && instoffset < BIG && instoffset != 0)
                                return C_SECON;
                        instoffset = s->value + a->offset + INITDAT;
/* not sure why this barfs */
return C_LCON;
/*
                        if(instoffset == 0)
                                return C_ZCON;
                        if(instoffset >= -0x1000 && instoffset <= 0xfff)
                                return C_SCON;
                        if((instoffset & 0x3ff) == 0)
                                return C_UCON;
                        return C_LCON;
*/

                case D_AUTO:
                        instoffset = autosize + a->offset;
                        if(instoffset >= -BIG && instoffset < BIG)
                                return C_SACON;
                        return C_LACON;

                case D_PARAM:
                        instoffset = autosize + a->offset + 4L;
                        if(instoffset >= -BIG && instoffset < BIG)
                                return C_SACON;
                        return C_LACON;
                }
                return C_GOK;

        case D_BRANCH:
                return C_SBRA;
        }
        return C_GOK;
}

Optab*
oplook(Prog *p)
{
        int a1, a2, a3, r;
        char *c1, *c3;
        Optab *o, *e;

        a1 = p->optab;
        if(a1)
                return optab+(a1-1);
        a1 = p->from.class;
        if(a1 == 0) {
                a1 = aclass(&p->from) + 1;
                p->from.class = a1;
        }
        a1--;
        a3 = p->to.class;
        if(a3 == 0) {
                a3 = aclass(&p->to) + 1;
                p->to.class = a3;
        }
        a3--;
        a2 = C_NONE;
        if(p->reg != NREG)
                a2 = C_REG;
        r = p->as;
        o = oprange[r].start;
        if(o == 0)
                o = oprange[r].stop; /* just generate an error */
        e = oprange[r].stop;
        c1 = xcmp[a1];
        c3 = xcmp[a3];
        for(; o<e; o++)
                if(o->a2 == a2)
                if(c1[o->a1])
                if(c3[o->a3]) {
                        p->optab = (o-optab)+1;
                        return o;
                }
        diag("illegal combination %A %d %d %d",
                p->as, a1, a2, a3);
        if(1||!debug['a'])
                prasm(p);
        if(o == 0)
                errorexit();
        return o;
}

int
cmp(int a, int b)
{

        if(a == b)
                return 1;
        switch(a) {
        case C_LCON:
                if(b == C_ZCON || b == C_SCON || b == C_UCON)
                        return 1;
                break;
        case C_UCON:
                if(b == C_ZCON)
                        return 1;
                break;
        case C_SCON:
                if(b == C_ZCON)
                        return 1;
                break;
        case C_LACON:
                if(b == C_SACON)
                        return 1;
                break;
        case C_LBRA:
                if(b == C_SBRA)
                        return 1;
                break;
        case C_ELEXT:
                if(b == C_ESEXT)
                        return 1;
                break;
        case C_LEXT:
                if(b == C_SEXT ||
                   b == C_ESEXT || b == C_OSEXT ||
                   b == C_ELEXT || b == C_OLEXT)
                        return 1;
                break;
        case C_SEXT:
                if(b == C_ESEXT || b == C_OSEXT)
                        return 1;
                break;
        case C_ELAUTO:
                if(b == C_ESAUTO)
                        return 1;
                break;
        case C_LAUTO:
                if(b == C_SAUTO ||
                   b == C_ESAUTO || b == C_OSAUTO ||
                   b == C_ELAUTO || b == C_OLAUTO)
                        return 1;
                break;
        case C_SAUTO:
                if(b == C_ESAUTO || b == C_OSAUTO)
                        return 1;
                break;
        case C_REG:
                if(b == C_ZCON)
                        return 1;
                break;
        case C_LOREG:
                if(b == C_ZOREG || b == C_SOREG)
                        return 1;
                break;
        case C_SOREG:
                if(b == C_ZOREG)
                        return 1;
                break;

        case C_ANY:
                return 1;
        }
        return 0;
}

int
ocmp(const void *a1, const void *a2)
{
        Optab *p1, *p2;
        int n;

        p1 = (Optab*)a1;
        p2 = (Optab*)a2;
        n = p1->as - p2->as;
        if(n)
                return n;
        n = p1->a1 - p2->a1;
        if(n)
                return n;
        n = p1->a2 - p2->a2;
        if(n)
                return n;
        n = p1->a3 - p2->a3;
        if(n)
                return n;
        return 0;
}

void
buildop(void)
{
        int i, n, r;

        for(i=0; i<C_NCLASS; i++)
                for(n=0; n<C_NCLASS; n++)
                        xcmp[i][n] = cmp(n, i);
        for(n=0; optab[n].as != AXXX; n++)
                ;
        qsort(optab, n, sizeof(optab[0]), ocmp);
        for(i=0; i<n; i++) {
                r = optab[i].as;
                oprange[r].start = optab+i;
                while(optab[i].as == r)
                        i++;
                oprange[r].stop = optab+i;
                i--;
                
                switch(r)
                {
                default:
                        diag("unknown op in build: %A", r);
                        errorexit();
                case AADD:
                        oprange[AADDX] = oprange[r];
                        oprange[ASUB] = oprange[r];
                        oprange[ASUBX] = oprange[r];
                        oprange[AMUL] = oprange[r];
                        oprange[AXOR] = oprange[r];
                        oprange[AXNOR] = oprange[r];
                        oprange[AAND] = oprange[r];
                        oprange[AANDN] = oprange[r];
                        oprange[AOR] = oprange[r];
                        oprange[AORN] = oprange[r];
                        oprange[ASLL] = oprange[r];
                        oprange[ASRL] = oprange[r];
                        oprange[ASRA] = oprange[r];
                        oprange[AADDCC] = oprange[r];
                        oprange[AADDXCC] = oprange[r];
                        oprange[ATADDCC] = oprange[r];
                        oprange[ATADDCCTV] = oprange[r];
                        oprange[ASUBCC] = oprange[r];
                        oprange[ASUBXCC] = oprange[r];
                        oprange[ATSUBCC] = oprange[r];
                        oprange[ATSUBCCTV] = oprange[r];
                        oprange[AXORCC] = oprange[r];
                        oprange[AXNORCC] = oprange[r];
                        oprange[AANDCC] = oprange[r];
                        oprange[AANDNCC] = oprange[r];
                        oprange[AORCC] = oprange[r];
                        oprange[AORNCC] = oprange[r];
                        oprange[AMULSCC] = oprange[r];
                        oprange[ASAVE] = oprange[r];
                        oprange[ARESTORE] = oprange[r];
                        break;
                case AMOVB:
                        oprange[AMOVH] = oprange[r];
                        oprange[AMOVHU] = oprange[r];
                        oprange[AMOVBU] = oprange[r];
                        oprange[ASWAP] = oprange[r];
                        oprange[ATAS] = oprange[r];
                        break;
                case ABA:
                        oprange[ABN] = oprange[r];
                        oprange[AFBA] = oprange[r];
                        oprange[AFBN] = oprange[r];
                        break;
                case ABE:
                        oprange[ABCC] = oprange[r];
                        oprange[ABCS] = oprange[r];
                        oprange[ABGE] = oprange[r];
                        oprange[ABGU] = oprange[r];
                        oprange[ABG] = oprange[r];
                        oprange[ABLEU] = oprange[r];
                        oprange[ABLE] = oprange[r];
                        oprange[ABL] = oprange[r];
                        oprange[ABNEG] = oprange[r];
                        oprange[ABNE] = oprange[r];
                        oprange[ABPOS] = oprange[r];
                        oprange[ABVC] = oprange[r];
                        oprange[ABVS] = oprange[r];

                        oprange[AFBE] = oprange[r];
                        oprange[AFBG] = oprange[r];
                        oprange[AFBGE] = oprange[r];
                        oprange[AFBL] = oprange[r];
                        oprange[AFBLE] = oprange[r];
                        oprange[AFBLG] = oprange[r];
                        oprange[AFBNE] = oprange[r];
                        oprange[AFBO] = oprange[r];
                        oprange[AFBU] = oprange[r];
                        oprange[AFBUE] = oprange[r];
                        oprange[AFBUG] = oprange[r];
                        oprange[AFBUGE] = oprange[r];
                        oprange[AFBUL] = oprange[r];
                        oprange[AFBULE] = oprange[r];
                        break;
                case ATA:
                        oprange[ATCC] = oprange[r];
                        oprange[ATCS] = oprange[r];
                        oprange[ATE] = oprange[r];
                        oprange[ATGE] = oprange[r];
                        oprange[ATGU] = oprange[r];
                        oprange[ATG] = oprange[r];
                        oprange[ATLEU] = oprange[r];
                        oprange[ATLE] = oprange[r];
                        oprange[ATL] = oprange[r];
                        oprange[ATNEG] = oprange[r];
                        oprange[ATNE] = oprange[r];
                        oprange[ATN] = oprange[r];
                        oprange[ATPOS] = oprange[r];
                        oprange[ATVC] = oprange[r];
                        oprange[ATVS] = oprange[r];
                        break;
                case AFADDD:
                        oprange[AFADDF] = oprange[r];
                        oprange[AFADDX] = oprange[r];
                        oprange[AFDIVD] = oprange[r];
                        oprange[AFDIVF] = oprange[r];
                        oprange[AFDIVX] = oprange[r];
                        oprange[AFMULD] = oprange[r];
                        oprange[AFMULF] = oprange[r];
                        oprange[AFMULX] = oprange[r];
                        oprange[AFSUBD] = oprange[r];
                        oprange[AFSUBF] = oprange[r];
                        oprange[AFSUBX] = oprange[r];
                        break;
                case AFCMPD:
                        oprange[AFCMPF] = oprange[r];
                        oprange[AFCMPX] = oprange[r];
                        oprange[AFCMPED] = oprange[r];
                        oprange[AFCMPEF] = oprange[r];
                        oprange[AFCMPEX] = oprange[r];
                        break;
                case AFABSF:
                        oprange[AFMOVDF] = oprange[r];
                        oprange[AFMOVDW] = oprange[r];
                        oprange[AFMOVFD] = oprange[r];
                        oprange[AFMOVFW] = oprange[r];
                        oprange[AFMOVWD] = oprange[r];
                        oprange[AFMOVWF] = oprange[r];
                        oprange[AFNEGF] = oprange[r];
                        oprange[AFSQRTD] = oprange[r];
                        oprange[AFSQRTF] = oprange[r];
                        break;
                case AFMOVF:
                case AFMOVD:
                case AMOVW:
                case AMOVD:
                case AWORD:
                case ARETT:
                case AJMPL:
                case AJMP:
                case ACMP:
                case ANOP:
                case ATEXT:
                case ADIV:
                case ADIVL:
                case AMOD:
                case AMODL:
                        break;
                }
        }
}