Annotation of coherent/b/bin/c/n1/i386/gen1.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * n1/i386/gen1.c
        !             3:  * Print addresses,
        !             4:  * generate function prolog and epilog sequences,
        !             5:  * compile switches,
        !             6:  * and perform other non-tree-like functions.
        !             7:  * i386.
        !             8:  */
        !             9: 
        !            10: #ifdef   vax
        !            11: #include "INC$LIB:cc1.h"
        !            12: #else
        !            13: #include "cc1.h"
        !            14: #endif
        !            15: 
        !            16: /*
        !            17:  * These machine dependent variables hold values
        !            18:  * that are used by the machine dependent parts
        !            19:  * of register and/or temporary storage allocation.
        !            20:  * They are set up by routines in this file.
        !            21:  */
        !            22: ival_t maxauto;                /* Max autos in this function   */
        !            23: ival_t maxtemp;                /* Max temps in this function   */
        !            24: ival_t curtemp;                /* Current temp                 */
        !            25: PREGSET        regbusy;                /* Busy flags                   */
        !            26: 
        !            27: /*
        !            28:  * Convert register code to addressing mode for the register.
        !            29:  * This is either stashed in an AFIELD or
        !            30:  * written out to the intermediate file.
        !            31:  */
        !            32: static short   ramode[] = {
        !            33:        A_REAX, A_REDX, A_REBX, A_RECX,
        !            34:        A_RESI, A_REDI, A_RESP, A_REBP,
        !            35:        0,                                      /* EDX:EAX */
        !            36:        A_RAX,  A_RDX,  A_RBX,  A_RCX,
        !            37:        A_RSI,  A_RDI,  A_RSP,  A_RBP,
        !            38:        A_RAL,  A_RBL,  A_RCL,  A_RDL,
        !            39:        A_RAH,  A_RBH,  A_RCH,  A_RDH,
        !            40:        0                                       /* FPAC */
        !            41: };
        !            42: 
        !            43: /*
        !            44:  * Machine-dependent coder initialization.
        !            45:  * The i386 version zeros patcache[] entries which are
        !            46:  * inconsistent with specified machine-dependent variants or definitions.
        !            47:  * This lets the coder decide when the compiler is executed
        !            48:  * whether to use certain code table entries.
        !            49:  * Entries for DECVAX software floating point set the PDECVAX pattern flag.
        !            50:  * Entries for IEEE software floating point set the PIEEE pattern flag.
        !            51:  * Entries for NDP 80x87 IEEE hardware floating point set the PNDP pattern flag.
        !            52:  */
        !            53: coderinit()
        !            54: {
        !            55:        extern int patcsize;
        !            56:        register int i, flag;
        !            57:        register PATFLAG *pfp;
        !            58:        register PATFLAG pflag;
        !            59: 
        !            60:        /* Modify table entries in n1/i386/table1.c if NDP floating point. */
        !            61:        if (isvariant(VNDP)) {
        !            62:                reg[EDXEAX].r_rvalue = 0;
        !            63:                reg[FPAC].r_rvalue = KD;
        !            64:                pertype[F64].p_frreg = FPAC;
        !            65:        }
        !            66: 
        !            67:        /* Zap inappropriate code table entries. */
        !            68:        for (pfp=patcache, i=0; i < patcsize; pfp++, i++) {
        !            69:                if (((pflag = *pfp) & MDPFLAGS) != 0) {
        !            70:                        if (isvariant(VNDP)) {
        !            71:                                /* NDP hardware fp, zap software fp entries. */
        !            72:                                flag = ((pflag&PIEEE)!=0 || (pflag&PDECVAX)!=0)
        !            73:                                        && (pflag&PNDP)==0;
        !            74:                        } else {
        !            75:                                /*
        !            76:                                 * Software fp, zap NDP hardware fp entries
        !            77:                                 * and entries for inappropriate fp format.
        !            78:                                 */
        !            79: #if    DECVAX
        !            80:                                flag = ((pflag&PIEEE)!=0 || (pflag&PNDP)!=0)
        !            81:                                        && (pflag&PDECVAX)==0;
        !            82: #endif
        !            83: #if    IEEE
        !            84:                                flag = ((pflag&PDECVAX)!=0 || (pflag&PNDP)!=0)
        !            85:                                        && (pflag&PIEEE)==0;
        !            86: #endif
        !            87:                        }
        !            88:                        if (flag)
        !            89:                                *pfp = 0;       /* zero the pattern flags */
        !            90:                }
        !            91:        }
        !            92: }
        !            93: 
        !            94: /*
        !            95:  * Function prolog.
        !            96:  * Clear out max. values of autos and temps.
        !            97:  */
        !            98: doprolog()
        !            99: {
        !           100:        maxtemp = maxauto = maxbusy = blkflab = 0;
        !           101: }
        !           102: 
        !           103: /*
        !           104:  * This routine gets called just before the EPILOG item is put out.
        !           105:  * It puts out a single AUTOS item;
        !           106:  * this item tells CC2 how much auto space should be reserved.
        !           107:  * The second ival_t of the AUTOS record is a used register mask,
        !           108:  * CC2 should use it to decide whether it needs to save/restore registers
        !           109:  * but does not yet do so.
        !           110:  */
        !           111: doepilog()
        !           112: {
        !           113:        bput(AUTOS);
        !           114:        iput((ival_t)maxtemp);
        !           115:        iput((ival_t)maxbusy);
        !           116: }
        !           117: 
        !           118: /*
        !           119:  * Read in and save a new automatic (and register) variable allocation item.
        !           120:  * CC1 phase will toss out a single AUTOS item, just before the EPILOG,
        !           121:  * to tell CC2 how many bytes of automatic storage should be reserved.
        !           122:  * CC0 tosses one of these for each auto or register bound so that
        !           123:  * allocated space is not clobbered by temps during auto initialization.
        !           124:  */
        !           125: doautos()
        !           126: {
        !           127:        maxauto = iget();
        !           128:        regbusy = iget();
        !           129:        maxbusy |= regbusy;
        !           130: }
        !           131: 
        !           132: /*
        !           133:  * Unconditional jump.
        !           134:  */
        !           135: genubr(n)
        !           136: {
        !           137:        genl(ZJMP, n);
        !           138: }
        !           139: 
        !           140: /*
        !           141:  * Conditional jump.
        !           142:  */
        !           143: gencbr(c, n)
        !           144: {
        !           145:        genl(optab[c-MIOBASE][0], n);
        !           146: }
        !           147: 
        !           148: /*
        !           149:  * Generate code for switches.
        !           150:  * Look for special cases, etc. and generate the best type of switch logic.
        !           151:  * The switch value is in EAX (defined by SWREG in "cc1mch.h").
        !           152:  */
        !           153: genswitch(def, n)
        !           154: {
        !           155:        register ival_t l, r, u, adjust;
        !           156:        register int    i, lab0, lab1;
        !           157:        register char   *opp;
        !           158: 
        !           159:        /*
        !           160:         * If "n" is small, pretend the user said:
        !           161:         *      if (%eax == case0)
        !           162:         *              goto caselabel0;
        !           163:         *      if (%eax == case1)
        !           164:         *              goto caselabel1;
        !           165:         *      ...
        !           166:         */
        !           167:        if (n <= NSWITCH) {
        !           168:                for (i = 0; i < n; ++i) {
        !           169:                        if ((l = cases[i].c_val) == 0)
        !           170:                                genrr(ZOR, A_REAX, A_REAX);
        !           171:                        else
        !           172:                                genri(ZCMP, A_REAX, l);
        !           173:                        gencbr(EQ, cases[i].c_lab);
        !           174:                }
        !           175:                genubr(def);
        !           176:                maxbusy |= BEAX;
        !           177:                return;
        !           178:        }
        !           179: 
        !           180:        /*
        !           181:         * Try for a direct jump table if it seems reasonable to do so.
        !           182:         * The generated code adjusts the switch value to [0, range]
        !           183:         * with an add/subtract (or inc/dec),
        !           184:         * tests for out of range,
        !           185:         * and then does an indirect jump through the label table.
        !           186:         */
        !           187:        l = cases[0].c_val;
        !           188:        u = cases[n-1].c_val;
        !           189:        r = u-l;
        !           190:        if (r > 0 && r <= 3*n) {
        !           191:                if ((adjust = l) != 0) {
        !           192:                        opp = &optab[SUB-MIOBASE][0];
        !           193:                        if (adjust < 0) {
        !           194:                                opp = &optab[ADD-MIOBASE][0];
        !           195:                                adjust = -adjust;
        !           196:                        }
        !           197:                        if (adjust == 1)
        !           198:                                genr(opp[1], A_REAX);
        !           199:                        else
        !           200:                                genri(opp[0], A_REAX, adjust);
        !           201:                }
        !           202:                genri(ZCMP, A_REAX, r);
        !           203:                gencbr(UGT, def);                       /* out of range */
        !           204:                lab0 = newlab();
        !           205:                genone(ZIJMP, A_LID|sib(NOBASE, EAX, 4), lab0); /* jump indirect */
        !           206:                genlab(lab0);
        !           207:                for (i = 0; l <= u; ++l) {              /* write label table */
        !           208:                        lab0 = def;
        !           209:                        if (l == cases[i].c_val)
        !           210:                                lab0 = cases[i++].c_lab;
        !           211:                        genl(ZLPTR, lab0);
        !           212:                }
        !           213:                maxbusy |= BEAX;
        !           214:                return;
        !           215:        }
        !           216:        /*
        !           217:         * Table search.
        !           218:         * The generated code keeps a table length count in ECX
        !           219:         * and a table pointer in EDX.
        !           220:         */
        !           221:        lab0 = newlab();
        !           222:        gentwo(ZMOV, A_REDX, A_OFFS|A_LID|A_IMM, (ival_t)-4, lab0);
        !           223:        genri(ZMOV, A_RECX, (ival_t)n);         /* case count */
        !           224:        lab1 = newlab();
        !           225:        genlab(lab1);
        !           226:        genri(ZADD, A_REDX, (ival_t)4);         /* pointer to next value */
        !           227:        gentwo(ZCMP, A_REAX, A_XEDX);           /* compare to switch value */
        !           228:        genl(ZLOOPNE, lab1);                    /* loop while cases */
        !           229:        gencbr(NE, def);                        /* branch to default */
        !           230:        genone(ZIJMP, A_OFFS|A_XEDX, (ival_t)4*n); /* indirect jump to code */
        !           231:        genlab(lab0);
        !           232:        for (i = 0; i < n; ++i)
        !           233:                genone(ZLONG, A_OFFS|A_DIR, cases[i].c_val);
        !           234:        for (i = 0; i < n; ++i)
        !           235:                genl(ZLPTR, cases[i].c_lab);
        !           236:        maxbusy |= BEAX|BECX|BEDX;
        !           237: }
        !           238: 
        !           239: /*
        !           240:  * Output an address.
        !           241:  * "tp" is a pointer to a TREE.
        !           242:  * The "nsef" flag is true if no side effects are desired;
        !           243:  * it can be set from the code tables
        !           244:  * and is used to supress escape bytes on "LEA" instructions.
        !           245:  * The "pfx" array holds "npfx" address prefix bytes.
        !           246:  * There is some strangeness here.
        !           247:  * In memory a is LO and a+2 is HI; this is not the same for constants.
        !           248:  */
        !           249: genadr(tp, nsef, npfx, pfx)
        !           250: register TREE  *tp;
        !           251: unsigned char  pfx[];
        !           252: {
        !           253:        register int    op;
        !           254:        register int    bias;
        !           255:        register int    memf;
        !           256:        register int    byte;
        !           257:        register int    reg;
        !           258:        register ival_t ival;
        !           259:        int             mode;
        !           260:        int             offs;
        !           261:        lval_t          loffs;
        !           262:        int             lidn;
        !           263:        SYM             *gidp;
        !           264: 
        !           265:        static  char    basebias[] = {
        !           266:                0,      0,              /* S8,   U8,    */
        !           267:                1,      1,              /* S16,  U16,   */
        !           268:                2,      2,              /* S32,  U32,   */
        !           269:                2,      4,              /* F32,  F64,   */
        !           270:                0,                      /* BLK,         */
        !           271:                0,      1,      2,      /* FLD8, FLD16, FLD32 */
        !           272:                2,      2               /* PTR,  PTB    */
        !           273:        };
        !           274: 
        !           275:        /* Skip leaf nodes. */
        !           276:        while ((op=tp->t_op) == LEAF)
        !           277:                tp = tp->t_lp;
        !           278: 
        !           279:        /*
        !           280:         * The "HI" and "LO" options applied to a register node
        !           281:         * just call the "hihalf" and "lohalf" macros.
        !           282:         */
        !           283:        if (op == REG) {
        !           284:                reg = tp->t_reg;
        !           285:                while (npfx--) {
        !           286:                        reg = (pfx[npfx] == M_LO) ? lohalf(reg) : hihalf(reg);
        !           287:                        if (reg == -1)
        !           288:                                cbotch("hi/lo, reg=%d", tp->t_reg);
        !           289:                }
        !           290:                iput((ival_t)ramode[reg]);
        !           291:                return;
        !           292:        }
        !           293:        /*
        !           294:         * For constants and memory locations,
        !           295:         * the "HI" and "LO" macros dial the
        !           296:         * selected byte, word or dword out of the operand.
        !           297:         */
        !           298:        offs = 0;
        !           299:        memf = (op != ICON && op != LCON && op != DCON);
        !           300:        if (npfx) {
        !           301:                bias = basebias[tp->t_type];
        !           302:                while (npfx--) {
        !           303:                        byte = pfx[npfx];
        !           304:                        if (memf && (bias == 2 || bias == 4)) {
        !           305:                                if (byte == M_HI)
        !           306:                                        offs += bias;
        !           307:                        } else if (byte == M_LO)
        !           308:                                offs += bias;
        !           309:                        bias >>= 1;
        !           310:                }
        !           311:        }
        !           312: 
        !           313:        /*
        !           314:         * Constant nodes are used as immediate operands of instructions.
        !           315:         * Write the appropriate 32 bit chunk as an immediate operand.
        !           316:         */
        !           317:        if (!memf) {                            /* ICON, LCON or DCON */
        !           318:                if (op == ICON || op == LCON)   /* ICON or LCON */
        !           319:                        ival = tp->t_ival;
        !           320:                else {                          /* DCON */
        !           321:                        ival  = ((ival_t)(tp->t_dval[3+offs] & 0xFF));
        !           322:                        ival |= ((ival_t)(tp->t_dval[2+offs] & 0xFF)) <<  8;
        !           323:                        ival |= ((ival_t)(tp->t_dval[1+offs] & 0xFF)) << 16;
        !           324:                        ival |= ((ival_t)(tp->t_dval[offs]         )) << 24;
        !           325:                }
        !           326:                iput((ival_t)A_OFFS|A_IMM);
        !           327:                iput(ival);
        !           328:                return;
        !           329:        }
        !           330: 
        !           331:        /*
        !           332:         * Collect address.
        !           333:         * Turn the "f" argument on in the call
        !           334:         * to "gencoll" if this is a "lea", so that it
        !           335:         * won't generate immediate mode addressing
        !           336:         * when it shouldn't.
        !           337:         */
        !           338:        mode = A_DIR;
        !           339:        loffs = offs;
        !           340:        if (gencoll(tp, &mode, &loffs, &lidn, &gidp, 0, nsef) == 0)
        !           341:                cbotch("collect");
        !           342:        offs = loffs;
        !           343:        if (offs == 0)
        !           344:                iput((ival_t)mode);
        !           345:        else {
        !           346:                iput((ival_t)mode|A_OFFS);
        !           347:                iput((ival_t)offs);
        !           348:        }
        !           349:        if ((mode&A_LID) != 0)
        !           350:                iput((ival_t)lidn);
        !           351:        else if ((mode&A_GID) != 0)
        !           352:                sput(gidp->s_id);
        !           353: }
        !           354: 
        !           355: /*
        !           356:  * Walk down an address tree, building up the addressing mode,
        !           357:  * the offset and the symbol base for a general addressing item.
        !           358:  * Store the data back through the argument pointers.
        !           359:  * The caller must set the initial mode to "A_DIR" and the offset to 0. 
        !           360:  */
        !           361: gencoll(tp, modep, offsp, lidnp, gidpp, s, f)
        !           362: TREE   *tp;
        !           363: int    *modep;
        !           364: lval_t *offsp;
        !           365: int    *lidnp;
        !           366: SYM    **gidpp;
        !           367: int    s;
        !           368: int    f;
        !           369: {
        !           370:        register int    op;
        !           371:        register lval_t offs;
        !           372:        register int    mode;
        !           373: 
        !           374:        while ((op=tp->t_op) == LEAF)
        !           375:                tp = tp->t_lp;
        !           376:        switch (op) {
        !           377: 
        !           378:        case ADDR:
        !           379:                if (gencoll(tp->t_lp, modep, offsp, lidnp, gidpp, s, f) == 0)
        !           380:                        return 0;
        !           381:                if (f == 0) {
        !           382:                        *modep &= ~A_AMOD;
        !           383:                        *modep |=  A_IMM;
        !           384:                }
        !           385:                break;
        !           386: 
        !           387:        case STAR:
        !           388:                if (gencoll(tp->t_lp, modep, offsp, lidnp, gidpp, s, 1) == 0)
        !           389:                        return 0;
        !           390:                break;
        !           391:                
        !           392:        case ADD:
        !           393:        case SUB:
        !           394:                if (gencoll(tp->t_lp, modep, offsp, lidnp, gidpp, s, f) == 0)
        !           395:                        return 0;
        !           396:                if (op == SUB)
        !           397:                        s = !s;
        !           398:                if (gencoll(tp->t_rp, modep, offsp, lidnp, gidpp, s, f) == 0)
        !           399:                        return 0;
        !           400:                break;
        !           401: 
        !           402:        case ICON:
        !           403:        case LCON:
        !           404:                offs = grabnval(tp);
        !           405:                if (s != 0)
        !           406:                        offs = -offs;
        !           407:                *offsp += offs;
        !           408:                break;
        !           409: 
        !           410:        case LID:
        !           411:                if ((*modep&(A_GID|A_LID))!=0 || s!=0)
        !           412:                        return 0;
        !           413:                *modep |= A_LID;
        !           414:                *lidnp  = tp->t_label;
        !           415:                goto lidgid;
        !           416: 
        !           417:        case GID:
        !           418:                if ((*modep&(A_GID|A_LID))!=0 || s!=0)
        !           419:                        return 0;
        !           420:                *modep |= A_GID;
        !           421:                *gidpp  = tp->t_sp;
        !           422:        lidgid:
        !           423:                *offsp += tp->t_offs;
        !           424:                break;
        !           425: 
        !           426:        case REG:
        !           427:                if ((*modep&A_AMOD)!=A_DIR || s!=0)
        !           428:                        return 0;
        !           429:                mode = ramode[tp->t_reg];
        !           430:                if ((mode & A_AMOD) != A_DR || mode == A_RESP)
        !           431:                        return 0;                       /* not dword index register */
        !           432:                *modep = A_XB | (mode & A_REGM);        /* corresponding index reg */
        !           433:                break;
        !           434: 
        !           435:        default:
        !           436:                return 0;
        !           437:        }
        !           438:        return 1;
        !           439: }
        !           440: 
        !           441: /*
        !           442:  * Construct an SIB addressing mode using the given base, index and scale.
        !           443:  */
        !           444: int
        !           445: sib(b, i, s) register int b, i, s;
        !           446: {
        !           447:        switch(s) {
        !           448:        case 1:         s = 0;          break;
        !           449:        case 2:         s = 1;          break;
        !           450:        case 4:         s = 2;          break;
        !           451:        case 8:         s = 3;          break;
        !           452:        default:        cbotch("sib, s=%d", s);
        !           453:        }
        !           454:        i = ramode[i] & A_REGM;
        !           455:        b = (b == NOBASE) ? 5 : (ramode[b] & A_REGM);
        !           456:        return A_XSIB | (s << 6) | (i << 3) | b;
        !           457: }
        !           458: 
        !           459: /*
        !           460:  * Output an instruction that takes a single register as an operand.
        !           461:  */
        !           462: genr(op, r)
        !           463: {
        !           464:        bput(CODE);
        !           465:        bput(op);
        !           466:        iput((ival_t)r);
        !           467: }
        !           468: 
        !           469: /*
        !           470:  * Output an instruction that takes two registers as operands.
        !           471:  */
        !           472: genrr(op, r1, r2)
        !           473: {
        !           474:        bput(CODE);
        !           475:        bput(op);
        !           476:        iput((ival_t)r1);
        !           477:        iput((ival_t)r2);
        !           478: }
        !           479: 
        !           480: /*
        !           481:  * Output an instruction that takes a register and an immediate constant value.
        !           482:  */
        !           483: genri(op, r, i) int op; int r; ival_t i;
        !           484: {
        !           485:        bput(CODE);
        !           486:        bput(op);
        !           487:        iput((ival_t)r);
        !           488:        iput((ival_t)A_OFFS|A_IMM);
        !           489:        iput(i);
        !           490: }
        !           491: 
        !           492: /*
        !           493:  * Output an instruction with a single local label parameter.
        !           494:  */
        !           495: genl(op, l)
        !           496: {
        !           497:        bput(CODE);
        !           498:        bput(op);
        !           499:        iput((ival_t)A_LID|A_DIR);
        !           500:        iput((ival_t)l);
        !           501: }
        !           502: 
        !           503: /*
        !           504:  * Output an instruction that takes a single global identifier as an operand.
        !           505:  */
        !           506: geng(op, g)
        !           507: char   *g;
        !           508: {
        !           509:        bput(CODE);
        !           510:        bput(op);
        !           511:        iput((ival_t)A_GID|A_DIR);
        !           512:        sput(g);
        !           513: }
        !           514: 
        !           515: /*
        !           516:  * Output an instruction that takes an immediate constant value.
        !           517:  */
        !           518: geni(op, i)
        !           519: {
        !           520:        bput(CODE);
        !           521:        bput(op);
        !           522:        iput((ival_t)A_OFFS|A_IMM);
        !           523:        iput((ival_t)i);
        !           524: }
        !           525: 
        !           526: /* end of n1/i386/gen1.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.