Annotation of coherent/d/bin/cc/c/n1/i8086/gen1.c, revision 1.1.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.