Annotation of coherent/d/bin/cc/c/n1/i8086/gen1.c, revision 1.1

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

unix.superglobalmegacorp.com

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