Annotation of coherent/b/bin/as/build.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * 80386 Assembler Build output code.
                      3:  */
                      4: #include <asm.h>
                      5: #include <asflags.h>
                      6: #include <y_tab.h>
                      7: #include <symtab.h>
                      8: 
                      9: static symt *st;
                     10: static struct expr *opList[3];
                     11: static int ct;
                     12: 
                     13: /* as checkop runs it sets the following fields */
                     14: static expr *addr, *displ, *immed, *immedx;
                     15: static char mod, rm, reg, scale, index, base, immed8;
                     16: 
                     17: static unsigned long uflags;
                     18: #define U_REL8 1       /* relative 8  bit operand */
                     19: #define U_REL16        2       /* relative 16 bit operand */
                     20: #define U_RELI 3       /* we get to choose 8 0r 16 bit */
                     21: #define U_REL_MASK 3
                     22: 
                     23: #define U_RMS   0x04   /* mod/rm .16 */
                     24: #define U_RML   0x08   /* mod/rm .32 */
                     25: #define U_IMM8  0x10   /* 8  bit immediate field */
                     26: #define U_IMM16         0x20   /* 16 bit immediate field */
                     27: #define U_IMM16X 0x40  /* 16 bit second immediate field */
                     28: #define U_IMM32         0x80   /* 32 bit immediate field */
                     29: #define U_IMM32X 0x100 /* 32 bit second immediate field */
                     30: #define U_ADR16  0x200 /* 16 bit direct address */
                     31: #define U_ADR32  0x400 /* 32 bit direct address */
                     32: #define U_DSP8  0x800  /* 8 bit displacment with mod/rm */
                     33: #define U_DSP    0x1000        /* 16 or 32 bit displacment with mod/rm */
                     34: #define U_CTL   0x2000 /* control register */
                     35: 
                     36: /*
                     37:  * Build indefinate opcode. On 80386 thats everything.
                     38:  * First try all instrs not in the wrong mode.
                     39:  * Then try the instrs in the wrong mode.
                     40:  */
                     41: buildind(label, op, oper)
                     42: parm *label;
                     43: register opc *op;
                     44: register expr *oper;
                     45: {
                     46:        int i;
                     47:        unsigned short wrongMode;
                     48: 
                     49:        buildlab(label);
                     50: 
                     51:        ct = countList((parm *)oper);
                     52: 
                     53:        if (ct > 3) {
                     54:                yyerror("Too many operands");
                     55:                /* No 386 opcode has more than three operands. */
                     56:                return (1);
                     57:        }
                     58: 
                     59:        if (fswitch)    /* reverse operand order */
                     60:                for (i = ct; i--; oper = oper->next)
                     61:                        opList[i] = oper;
                     62:        else            /* normal operand order */
                     63:                for (i = 0; i < ct; i++, oper = oper->next)
                     64:                        opList[i] = oper;
                     65: 
                     66:        /* try the stuff not in the wrong mode */
                     67:        wrongMode = longMode ? WORD_MODE : LONG_MODE;
                     68:        for (i = 0; i < choices; i++) {
                     69:                st = typTab + op[i].kind;
                     70:                if (!(st->bldr & wrongMode) && !buildop(op + i))
                     71:                        return(0);
                     72:        }
                     73: 
                     74:        /* now try the wrong mode choices */
                     75:        for (i = 0; i < choices; i++) {
                     76:                st = typTab + op[i].kind;
                     77:                if ((st->bldr & wrongMode) && !buildop(op + i))
                     78:                        return(0);
                     79:        }
                     80: 
                     81:        yyerror("Illegal combination of opcode and operands");
                     82:        /* Although the opcode is valid and the operands are valid,
                     83:         * there is no form of this opcode which takes this combination
                     84:         * of operands in this order. If there are a lot of these messages
                     85:         * the -f command option may be in the wrong sense. */
                     86:        return(1);
                     87: }
                     88: 
                     89: /*
                     90:  * Convienience function for checkop.
                     91:  * Checks if displacment is byte or longer.
                     92:  */
                     93: static void
                     94: setDisp(this)
                     95: register expr *this;
                     96: {
                     97:        long d;
                     98: 
                     99:        if ((NULL != this->ref) ||
                    100:            (d = this->exp) < -128 || d > 127) {
                    101:                uflags |= U_DSP;
                    102:                mod = 2;
                    103:        }
                    104:        else {
                    105:                uflags |= U_DSP8;
                    106:                mod = 1;
                    107:        }
                    108:        displ = this;
                    109: }
                    110: 
                    111: /*
                    112:  * Check if operator validly fits mode.
                    113:  * return 1 for false zero for true.
                    114:  */
                    115: static
                    116: checkop(this, type)
                    117: register expr *this;
                    118: unsigned short type;
                    119: {
                    120:        register sym *r1;
                    121:        long d;
                    122:        int  regsz;
                    123: 
                    124:        r1 = this->r1;
                    125: 
                    126:        switch (type) {
                    127:        case m8:
                    128:        case m16:
                    129:        case m32:
                    130:        case m64:
                    131:        case m80:
                    132:                regsz = -1;     /* can't be a register */
                    133:                break;
                    134: 
                    135:        case rm8:
                    136:                regsz = 1;      /* reg must be 1 long */
                    137:                break;
                    138: 
                    139:        case rm16:
                    140:                regsz = 2;      /* reg must be 2 long */
                    141:                break;
                    142: 
                    143:        case rm32:
                    144:                regsz = 4;      /* reg must be 4 long */
                    145:                break;
                    146: 
                    147:        case reli:      /* near branch */
                    148:                if (!(lflags & A_INDIR)) {
                    149:                        uflags = U_RELI;
                    150:                        return (T_D != this->mode);
                    151:                }
                    152:                regsz = longMode ? 4 : 2;
                    153:                break;
                    154: 
                    155:        case rel8:      /* near branch */
                    156:                uflags = U_REL8;
                    157:                return (T_D != this->mode);
                    158:                    
                    159:        case rel16:     /* medium or long branch */
                    160:                uflags = U_REL16;
                    161:                return (T_D != this->mode);
                    162:                    
                    163:        case mem32:     /* 32 bit simple address */
                    164:                uflags |= U_ADR32;
                    165:                rm = 5;
                    166:                return (T_D != (addr = this)->mode);
                    167: 
                    168:        case mem16:     /* 16 bit simple address */
                    169:                uflags |= U_ADR16;
                    170:                rm = 6;
                    171:                return (T_D != (addr = this)->mode);
                    172: 
                    173: 
                    174:        case imm8:
                    175:                uflags |= U_IMM8;
                    176:                immed8 = this->exp;
                    177:                return (this->ref != NULL ||
                    178:                        this->mode != T_IMM ||
                    179:                        this->exp < -128 ||
                    180:                        this->exp > 255);
                    181: 
                    182:        case imm8s:
                    183:                uflags |= U_IMM8;
                    184:                immed8 = this->exp;
                    185:                return (this->ref != NULL ||
                    186:                        this->mode != T_IMM ||
                    187:                        this->exp < -128 ||
                    188:                        this->exp > 127);
                    189: 
                    190:        case imm16x:
                    191:                uflags |= U_IMM16X;
                    192:                d = (immedx = this)->exp;
                    193:                return (this->mode != T_IMM ||
                    194:                        d < -32768L ||
                    195:                        d > 65535L);
                    196: 
                    197:        case imm16:
                    198:                uflags |= U_IMM16;
                    199:                d = (immed = this)->exp;
                    200:                return (this->mode != T_IMM ||
                    201:                        d < -32768L ||
                    202:                        d > 65535L);
                    203: 
                    204:        case imm32x:
                    205:                uflags |= U_IMM32X;
                    206:                immedx = this;
                    207:                return (this->mode != T_IMM);
                    208: 
                    209:        case moffs:
                    210:                uflags |= U_IMM32;
                    211:                immed = this;
                    212:                return (this->mode != T_D);
                    213: 
                    214:        case imm32:
                    215:                uflags |= U_IMM32;
                    216:                immed = this;
                    217:                return (this->mode != T_IMM);
                    218: 
                    219:        case con1:
                    220:                return (this->mode != T_IMM ||
                    221:                        this->exp != 1);
                    222: 
                    223:        case con3:
                    224:                return (this->mode != T_IMM ||
                    225:                        this->exp != 3);
                    226: 
                    227:        case al:
                    228:                return (this->mode != T_R ||
                    229:                        r1->flag != ORD_REG ||
                    230:                        r1->size != 1 ||
                    231:                        r1->loc != 0);
                    232: 
                    233:        case ax:
                    234:                return (this->mode != T_R ||
                    235:                        r1->flag != ORD_REG ||
                    236:                        r1->size != 2 ||
                    237:                        r1->loc != 0);
                    238: 
                    239:        case eax:
                    240:                return (this->mode != T_R ||
                    241:                        r1->flag != ORD_REG ||
                    242:                        r1->size != 4 ||
                    243:                        r1->loc != 0);
                    244: 
                    245:        case r16:
                    246:                if (this->mode != T_R || r1->flag != ORD_REG || r1->size != 2)
                    247:                        return (1);
                    248:                reg = r1->loc;
                    249:                return (0);
                    250: 
                    251:        case atdx:
                    252:                if (this->mode != T_RI || r1->flag != ORD_REG ||
                    253:                    r1->size != 2 || r1->loc != 2)
                    254:                        return(1);
                    255:                lflags &= ~A_SHORT;
                    256:                return(0);
                    257: 
                    258:        case dx:
                    259:                if (this->mode != T_R || r1->flag != ORD_REG ||
                    260:                    r1->size != 2 || r1->loc != 2)
                    261:                        return(1);
                    262:                lflags &= ~A_SHORT;
                    263:                return(0);
                    264: 
                    265:        case cl:
                    266:                return (this->mode != T_R ||
                    267:                        r1->flag != ORD_REG ||
                    268:                        r1->size != 1 ||
                    269:                        r1->loc != 1);
                    270: 
                    271:        case ds:
                    272:                return (this->mode != T_R ||
                    273:                        r1->flag != SEG_REG ||
                    274:                        r1->loc != 3);
                    275: 
                    276:        case es:
                    277:                return (this->mode != T_R ||
                    278:                        r1->flag != SEG_REG ||
                    279:                        r1->loc != 0);
                    280: 
                    281:        case ss:
                    282:                return (this->mode != T_R ||
                    283:                        r1->flag != SEG_REG ||
                    284:                        r1->loc != 2);
                    285: 
                    286:        case fs:
                    287:                return (this->mode != T_R ||
                    288:                        r1->flag != SEG_REG ||
                    289:                        r1->loc != 4);
                    290: 
                    291:        case gs:
                    292:                return (this->mode != T_R ||
                    293:                        r1->flag != SEG_REG ||
                    294:                        r1->loc != 5);
                    295: 
                    296:        case cs:
                    297:                return (this->mode != T_R ||
                    298:                        r1->flag != SEG_REG ||
                    299:                        r1->loc != 1);
                    300: 
                    301:        case sreg:
                    302:                if (this->mode != T_R || r1->flag != SEG_REG)
                    303:                        return (1);
                    304:                reg = r1->loc;
                    305:                return (0);
                    306: 
                    307:        case st0:
                    308:                if (this->mode != T_FP || this->exp)
                    309:                        return (1);
                    310:                return (0);
                    311: 
                    312:        case fpreg:
                    313:                if (this->mode != T_FP)
                    314:                        return (1);
                    315:                reg = this->exp;
                    316:                return (0);
                    317: 
                    318:        case ctlreg:
                    319:                if (this->mode != T_R || r1->flag != CTL_REG)
                    320:                        return (1);
                    321:                uflags |= U_CTL;
                    322:                rm = r1->loc;
                    323:                return (0);
                    324: 
                    325:        case dbreg:
                    326:                if (this->mode != T_R || r1->flag != DEB_REG)
                    327:                        return (1);
                    328:                uflags |= U_CTL;
                    329:                rm = r1->loc;
                    330:                return (0);
                    331: 
                    332:        case treg:
                    333:                if (this->mode != T_R || r1->flag != TST_REG)
                    334:                        return (1);
                    335:                uflags |= U_CTL;
                    336:                rm = r1->loc;
                    337:                return (0);
                    338: 
                    339:        case r32:
                    340:                if (this->mode != T_R || r1->flag != ORD_REG || r1->size != 4)
                    341:                        return (1);
                    342:                reg = r1->loc;
                    343:                return (0);
                    344: 
                    345:        case r8:
                    346:                if (this->mode != T_R || r1->flag != ORD_REG || r1->size != 1)
                    347:                        return (1);
                    348:                reg = r1->loc;
                    349:                return (0);
                    350:        }
                    351: 
                    352:        /*
                    353:         * If we get to here the mode must be rm16 or rm32.
                    354:         * The table mode has been used to decide the proper
                    355:         * size for registers. Decide which is the real mode.
                    356:         */
                    357:        if (longMode)
                    358:                if (lflags & A_SHORT)
                    359:                        type = rm16;
                    360:                else
                    361:                        type = rm32;
                    362:        else
                    363:                if (lflags & A_LONG)
                    364:                        type = rm32;
                    365:                else
                    366:                        type = rm16;
                    367: 
                    368:        switch(type) {
                    369:        case rm32:      /* r/m 32 See Tables 17-3 and 17-4 */
                    370:                uflags |= U_RML;
                    371:                switch (this->mode) {
                    372:                case T_D:       /* all 32 bit disp must be good */
                    373:                        mod = 0;
                    374:                        rm = 5;
                    375:                        uflags |= U_DSP;
                    376:                        displ = this;
                    377:                        return (0);
                    378: 
                    379:                case T_RID:
                    380:                        setDisp(this);
                    381:                        if (4 == (rm = r1->loc)) { /* disp (%esp) */
                    382:                                base = 4;       /* base = %esp */
                    383:                                index = 4;      /* no index */
                    384:                        }
                    385:                        return (0);
                    386: 
                    387:                case T_R:       /* eax | ecx || edx || ebx || esi || edi */
                    388:                        if ((r1->size != regsz) || (r1->flag != ORD_REG))
                    389:                                return (1);
                    390:                        rm  = r1->loc;
                    391:                        mod = 3;
                    392:                        return(0);
                    393: 
                    394:                case T_RI:
                    395:                        switch (rm = r1->loc) {
                    396:                        case 5: /* ( %ebp ) */
                    397:                                mod = 1;        /* 0 ( %ebp ) */
                    398:                                uflags |= U_DSP8; /* force displacment 0 */
                    399:                                displ = this;
                    400:                                break;
                    401:                        case 4: /* ( %esp ) */
                    402:                                base = 4;       /* %sp */
                    403:                                index = 4;      /* no index */
                    404:                        default: /* (eax | ecx | edx | ebx | esi | edi) */
                    405:                                mod = 0;
                    406:                        }
                    407: 
                    408:                        return (0);
                    409: 
                    410:                case T_RIS:
                    411:                        if (4 == (index = r1->loc)) /* can't index %esp */
                    412:                                return (1);
                    413: 
                    414:                        rm = 4;         /* use sib */
                    415:                        mod = 0;        /* no disp */
                    416:                        base = 5;       /* no base */
                    417:                        uflags |= U_DSP;
                    418:                        scale = this->scale;
                    419:                        index = r1->loc;
                    420:                        displ = this;
                    421:                        return (0);
                    422: 
                    423:                case T_RIX:             
                    424:                case T_RIXS:
                    425:                        /* can't index esp */
                    426:                        if (4 == (index = this->r2->loc))
                    427:                                return(1);
                    428: 
                    429:                        if (5 != (base = r1->loc)) {
                    430:                                mod = 0;
                    431:                                rm = 4;
                    432:                                scale = this->scale;
                    433:                                return (0);
                    434:                        } /* if base %ebp use T_RIXDS */
                    435: 
                    436:                case T_RIXD:
                    437:                case T_RIXDS:
                    438:                        /* can't index esp */
                    439:                        if (4 == (index = this->r2->loc))
                    440:                                return (1);
                    441: 
                    442:                        base = r1->loc;
                    443:                        setDisp(this);
                    444: 
                    445:                        rm = 4;
                    446:                        scale = this->scale;
                    447:                        return (0);
                    448: 
                    449:                case T_RIDS:
                    450:                        if (4 == (index = r1->loc))     /* can't index sp */
                    451:                                return (1);
                    452: 
                    453:                        mod = 0;
                    454:                        uflags |= U_DSP;
                    455:                        scale = this->scale;
                    456:                        rm = 4;
                    457:                        base = 5;
                    458:                        displ = this;
                    459:                        return (0);
                    460:                }
                    461:                return (1);
                    462: 
                    463:        case rm16:      /* r/m 16 */
                    464:                uflags |= U_RMS;
                    465:                switch (this->mode) {
                    466:                case T_RI:      /* register indirect */
                    467:                        switch ((int)r1->loc) {
                    468:                        case 6: /* (%si) */
                    469:                                rm = 4; break;
                    470:                        case 7: /* (%di) */
                    471:                                rm = 5; break;
                    472:                        case 3: /* (%bx) */
                    473:                                rm = 7; break;
                    474:                        default:
                    475:                                return (1);
                    476:                        }
                    477:                        mod = 0;
                    478:                        return (0);
                    479: 
                    480:                case T_R:       /* register */
                    481:                        if ((r1->size != regsz) || (r1->flag != ORD_REG))
                    482:                                return (1);
                    483:                        rm = r1->loc;
                    484:                        mod = 3;
                    485:                        return (0);
                    486:                        
                    487:                case T_D:       /* displacment */
                    488:                        if (this->exp < -32768L || this->exp > 65535L)
                    489:                                return(1);
                    490: 
                    491:                        mod = 0;
                    492:                        rm  = 6;
                    493:                        uflags |= U_DSP;
                    494:                        displ = this;
                    495:                        return (0);
                    496: 
                    497:                case T_RID:     /* register indirect displacment */
                    498:                        if (this->exp < -32768L || this->exp > 65535L)
                    499:                                return(1);
                    500: 
                    501:                        switch ((int)r1->loc) {
                    502:                        case 6: /* (%si) */
                    503:                                rm = 4; break;
                    504:                        case 7: /* (%di) */
                    505:                                rm = 5; break;
                    506:                        case 5: /* (%bp) */
                    507:                                rm = 6; break;
                    508:                        case 3: /* (%bx) */
                    509:                                rm = 7; break;
                    510:                        default:
                    511:                                return (1);
                    512:                        }
                    513: 
                    514:                        setDisp(this);
                    515:                        return (0);
                    516: 
                    517:                case T_RIXD:    /* register index displacment */
                    518:                        if (this->exp < -32768L || this->exp > 65535L)
                    519:                                return(1);
                    520: 
                    521:                        setDisp(this);
                    522:                        /* fall through */
                    523: 
                    524:                case T_RIX:     /* register index */
                    525:                        if (T_RIX == this->mode)
                    526:                                mod = 0;
                    527: 
                    528:                        switch ((int)r1->loc) {
                    529:                        case 3: /* %bx */
                    530:                                switch ((int)this->r2->loc) {
                    531:                                case 6: /* %si */
                    532:                                        rm = 0; break;
                    533:                                case 7: /* %di */
                    534:                                        rm = 1; break;
                    535:                                default:
                    536:                                        return (1);
                    537:                                }
                    538:                                break;
                    539:                        case 5: /* bp */
                    540:                                switch ((int)this->r2->loc) {
                    541:                                case 6: /* %si */
                    542:                                        rm = 2; break;
                    543:                                case 7: /* %di */
                    544:                                        rm = 3; break;
                    545:                                default:
                    546:                                        return (1);
                    547:                                }
                    548:                                break;
                    549:                        default:
                    550:                                return (1);
                    551:                        }
                    552:                        return (0);
                    553:                }
                    554:                return (1);
                    555:        }
                    556: }
                    557: 
                    558: /*
                    559:  * Chip errata message.
                    560:  */
                    561: errata(opcode)
                    562: {
                    563:        if (opcode && !nswitch)
                    564:                outab(opcode);
                    565:        else
                    566:                yywarn("This code may not work the same way on all chips");
                    567:                /* Some chips may not execute this code as expected. */
                    568: }
                    569: 
                    570: /*
                    571:  * Try to build an opcode.
                    572:  */
                    573: static
                    574: buildop(op)
                    575: opc *op;
                    576: {
                    577:        register unsigned short i, j;
                    578:        static short postSw = 0;
                    579:        static short lastOp = 0;
                    580:        static short lastFlags = 0;
                    581: 
                    582:        /* First check if everything is ok */
                    583:        if (st->operands != ct)
                    584:                return(1);
                    585: 
                    586:        uflags = base = mod = rm = reg = scale = index = 0;
                    587:        for (i = 0; i < ct; i++)
                    588:                if (checkop(opList[i], (unsigned short)(st->ap[i])))
                    589:                        return(1);
                    590: 
                    591:        /* deal with unusual stuff */
                    592:        if (st->bldr & (AMBIG_MATCH | TWO_OP_MULT | XTENDS)) {
                    593:                if (st->bldr & AMBIG_MATCH)
                    594:                        yywarn("Ambiguous operand length, %d bytes selected", 
                    595:                           (MOV_BYTE == op->code) ? 1 : (longMode ? 4 : 2));
                    596:                        /* The assembler cannot tell the operand length by
                    597:                         * looking at the opcode and the operands.
                    598:                         * You may want to do something like change
                    599:                         * \fBmov\fR to \fBmovl\fR. */
                    600: 
                    601:                /* 2 operand form of 3 operand multiply */
                    602:                if (st->bldr & TWO_OP_MULT) {
                    603:                        mod = 3;
                    604:                        rm  = opList[1]->r1->loc;
                    605:                }
                    606: 
                    607:                /* movsx and movzx have mixed 16 and 32 bit stuff */
                    608:                if (st->bldr & XTENDS)
                    609:                        lflags &= ~(O_LONG|O_SHORT);
                    610:        }
                    611: 
                    612:        /*
                    613:         * Only a few instructions are defined after a rep  or lock
                    614:         * Instructions valid after lock are marked but are
                    615:         * only valid if a memory location is accessed. This is
                    616:         * checked by excluding (mod == 3) which is rm is register.
                    617:         */
                    618:        if (postSw) {
                    619:                if (postSw & REP_INSTR)
                    620:                        if (!(st->bldr & AFTER_REP))
                    621:                                yywarn("Improper instruction following rep");
                    622:                                /* Only a few instructions
                    623:                                 * are valid after a rep instruction.
                    624:                                 * See your machine documentation for details.*/
                    625:                        else if (op->code == INSB || op->code == INSW)
                    626:                                errata(0);
                    627: 
                    628:                if ((postSw & LOCK_OP) &&
                    629:                    (!(st->bldr & AFTER_LOCK) || (3 == mod)))
                    630:                        yywarn("Improper instruction following lock");
                    631:                        /* Only a few instructions
                    632:                         * are valid after a lock instruction.
                    633:                         * See your machine documentation for details. */
                    634:        }
                    635:        postSw = st->bldr & (LOCK_OP | REP_INSTR);
                    636: 
                    637:        /* 
                    638:         * check for various chip errata
                    639:         * sometimes wave a dead chicken over your head to make things work
                    640:         */
                    641: #if 0
                    642:        /* See Intel chip errata for 80386-B1 17.
                    643:         * Coprocessor instruction crossing segment boundaries may hang chip.
                    644:         * Assume any 4's boundary is a potential boundary. */
                    645:        if ((st->bldr & FLOAT_ESC) &&
                    646:            (((st->bldr & FLOAT_PFX) ? 2 : 3) == (dot.loc % 4)))
                    647:                errata(NOP);
                    648: #endif
                    649: 
                    650:        /* See Intel chip errata for 80386-B1 23. */
                    651:        if (((lastOp == POPA) && (uflags & U_RML) && (mod != 3)) &&
                    652:                /* determine longmode of popa */
                    653:            ((longMode ? !(lastFlags & 2) : (lastFlags & 4)) ?
                    654:                /* longmode then if base index and either not %eax */
                    655:             ((rm == 4) && (index || base)) :
                    656:                /* not longmode any index was %eax */
                    657:             (!rm || ((rm == 4) && (!index || !base)))))
                    658:                errata(NOP);
                    659: 
                    660:        if (POP_MEM == op->code) {
                    661:                /* pop  %cs:mem */
                    662:                if (opList[0]->sg == 1)
                    663:                        errata(0);
                    664: 
                    665:                /* pop  n(%esp)  */
                    666:                if ((uflags & U_RML) && base == 4 && rm == 4 && mod)
                    667:                        errata(0);
                    668:        }
                    669:        
                    670:        /*
                    671:         * aam must be preceeded with special stuff on 80486
                    672:         * The idea is that there must be an xchg with a non 1 value.
                    673:         */
                    674:        if (op->code == AAM) {
                    675:                static char seq[8] = {
                    676:                        0x51,           /* push         %ecx */
                    677:                        0x33, 0xC9,     /* xor          %ecx, %ecx */
                    678:                        0x87, 0xC9,     /* xchg         %ecx, %ecx */
                    679:                        0xD4, 0x0A,     /* aam */
                    680:                        0x59            /* pop          %ecx */
                    681:                };
                    682: 
                    683:                if (nswitch)
                    684:                        errata(0);
                    685:                else {
                    686:                        for (i = 0; i < 8; i++)
                    687:                                outab(seq[i]);
                    688:                        return (0);
                    689:                }
                    690:        }
                    691:                        
                    692:        lastFlags = st->bldr;
                    693:        lastOp = op->code;
                    694: 
                    695:        if (lflags & A_INDIR) {
                    696:                lastFlags = (longMode ? LONG_MODE : WORD_MODE) | MODRM_BYTE;
                    697:                switch (lastOp) {
                    698:                case JMP_NEAR:
                    699:                        lastOp = JMP_INDIR;     break;
                    700:                case CALL_NEAR:
                    701:                        lastOp = CALL_INDIR;    break;
                    702:                default:
                    703:                        yyerror("Indirect mode on invalid instruction");
                    704:                        /* Indirection is only allowed on call and jump near
                    705:                         * instructions. */
                    706:                }
                    707:        }
                    708: 
                    709:        if (longMode) {
                    710:                if (lflags & A_SHORT) {
                    711:                        yywarn("16 bit addressing mode used in 32 bit code");
                    712:                        /* You probably don't want to do this.
                    713:                         * For example, you may want to say \fB(%esi)\fR, not
                    714:                         * \fB(%si)\fR. */
                    715:                        outab(PREFIX_AD);       /* address size prefix */
                    716:                }
                    717:                else
                    718:                        lflags |= A_LONG;
                    719: 
                    720:                if (lastFlags & WORD_MODE)
                    721:                        outab(PREFIX_OP);       /* operand size prefix */
                    722:        }
                    723:        else {
                    724:                if (lflags & A_LONG) {
                    725:                        yywarn("32 bit addressing mode used in 16 bit code");
                    726:                        /* You probably don't want to do this.
                    727:                         * For example, you may want to say \fB(%si)\fR, not
                    728:                         * \fB(%esi)\fR. */
                    729:                        outab(PREFIX_AD);       /* address size prefix */
                    730:                }
                    731:                else
                    732:                        lflags |= A_SHORT;
                    733: 
                    734:                if (lastFlags & LONG_MODE)
                    735:                        outab(PREFIX_OP); /* operand size prefix */
                    736:        }
                    737: 
                    738: #define ck(x, y) if (j & x) break; j |= x; outab(y); break;
                    739: 
                    740:        /* Put out nessisary prefix bytes */
                    741:        for (j = i = 0; i < ct; i++) {
                    742:                switch (opList[i]->sg) {
                    743:                case 0: /* es: */
                    744:                        ck(1, PREFIX_ES);
                    745:                case 1: /* cs: */
                    746:                        ck(2, PREFIX_CS);
                    747:                case 2: /* ss: */
                    748:                        ck(4, PREFIX_SS);
                    749:                case 3: /* ds: */
                    750:                        ck(8, PREFIX_DS);
                    751:                case 4: /* fs: */
                    752:                        ck(16, PREFIX_FS);
                    753:                case 5: /* gs: */
                    754:                        ck(32, PREFIX_GS);
                    755:                }
                    756:        }
                    757: 
                    758: #undef ck
                    759: 
                    760:        /* Then build the op code */
                    761: 
                    762:        /* Test for relative jump first */
                    763:        switch ((int)(uflags & U_REL_MASK)) {
                    764:        case U_REL16:   /* 16 or 32 bit branch */
                    765:                indBra(lastOp, NON_OP, opList[0]);
                    766:                return(0);
                    767: 
                    768:        case U_REL8:    /* 8 bit branch */
                    769:                indBra(NON_OP, lastOp, opList[0]);
                    770:                return(0);
                    771: 
                    772:        case U_RELI:    /* may become 8, 16 or 32 bit branch */
                    773:                switch (lastOp) {
                    774:                case JMP_NEAR:
                    775:                        indBra(lastOp, JMP_SHORT, opList[0]);
                    776:                        break;
                    777:                case CALL_NEAR:
                    778:                        indBra(lastOp, NON_OP, opList[0]);
                    779:                        break;
                    780:                default:        /* conditional jump */
                    781:                        indBra(lastOp + JCC_NEAR,
                    782:                               lastOp + JCC_SHORT, opList[0]);
                    783:                }
                    784:                return(0);
                    785:        }
                    786: 
                    787:        if (lastFlags & PFX_0F)
                    788:                outab(0x0F);
                    789: 
                    790:        if (lastFlags & FLOAT_PFX)
                    791:                outab(0x9B);
                    792: 
                    793:        if (lastFlags & MODRM_BYTE ||
                    794:            lastOp & 0xFF00)
                    795:                outab(lastOp >> 8);
                    796: 
                    797:        j = lastOp & 0xFF;
                    798: 
                    799:        if (lastFlags & ADD_REG)
                    800:                j += reg;
                    801: 
                    802:        if (lastFlags & MODRM_BYTE)
                    803:                reg = j;
                    804:        else
                    805:                outab(j);
                    806: 
                    807:        if (uflags & (U_RML|U_CTL))
                    808:                outrm32();
                    809:        else if (uflags & U_RMS)
                    810:                outrm16();
                    811: 
                    812:        if (uflags & U_IMM16)
                    813:                outrw(immed, 0);
                    814: 
                    815:        if (uflags & U_IMM32)
                    816:                outrl(immed, 0);
                    817: 
                    818:        if (uflags & U_IMM8)
                    819:                outab(immed8);
                    820: 
                    821:        if (uflags & U_IMM16X)
                    822:                outrw(immedx, 0);
                    823: 
                    824:        if (uflags & U_IMM32X)
                    825:                outrl(immedx, 0);
                    826: 
                    827:        if (uflags & U_ADR16)
                    828:                outrw(addr, 0);
                    829: 
                    830:        if (uflags & U_ADR32)
                    831:                outrl(addr, 0);
                    832: 
                    833:        return(0);
                    834: }
                    835: 
                    836: /*
                    837:  * Output mod/rm byte and maybe sib
                    838:  */
                    839: static
                    840: outrm32()
                    841: {
                    842:        short modrm, sib;
                    843: 
                    844:        if (uflags & U_CTL)     /* Special register used */
                    845:                modrm = (3 << 6) | (rm << 3) | reg;
                    846:        else
                    847:                modrm = (mod << 6) | (reg << 3) | rm;
                    848: 
                    849:        outab(modrm);
                    850:        if (4 == rm && 3 != mod) {
                    851:                sib = (scale << 6) | (index << 3) | base;
                    852:                outab(sib);
                    853:        }
                    854: 
                    855:        if (uflags & U_DSP8)
                    856:                outrb(displ, 0);
                    857: 
                    858:        else if (uflags & U_DSP)
                    859:                outrl(displ, 0);
                    860: }
                    861: 
                    862: /*
                    863:  * Output mod/rm byte
                    864:  */
                    865: static
                    866: outrm16()
                    867: {
                    868:        short modrm;
                    869: 
                    870:        modrm = (mod << 6) | (reg << 3) | rm;
                    871:        outab(modrm);
                    872: 
                    873:        if (uflags & U_DSP8)
                    874:                outrb(displ, 0);
                    875: 
                    876:        else if (uflags & U_DSP)
                    877:                outrw(displ, 0);
                    878: }
                    879: 
                    880: /*
                    881:  * Code for relative branches.
                    882:  * Save type of all branch operators on a list assuming shortest feasable.
                    883:  * If a type changes set xpass = 1.
                    884:  *
                    885:  * Pass logic in newPass goes to 2 only if xpass == 0 else it goes to 1
                    886:  *
                    887:  * There is an elegant algorithm for fixing up jumps between passes by
                    888:  * tree manipulation, this would reduce this to a two pass assembler.
                    889:  * Sadly it won't work. It assumes smooth code, that is if I change a
                    890:  * byte jump to a near jump the following addresses will change by addition.
                    891:  * In assembly language people can insert things like .align or .org which
                    892:  * break that assumption, the GNU compiler does this every few lines.
                    893:  *
                    894:  * Once the smooth code assumption is broken we no longer know that the
                    895:  * tree algorithm terminates at all, a byte jump can go to a longer jump
                    896:  * and back again in the next pass. To guarantee termination we start at
                    897:  * byte jumps and only go to longer jumps when we know it is forced. Once
                    898:  * we go to longer jump we never go back. This speeds the assembly of GNU
                    899:  * output by about 10 times.
                    900:  */
                    901: static unsigned braCt;         /* count of branches */
                    902: 
                    903: #define BYTE_J 0       /* byte jump length */
                    904: #define NEAR_J 1       /* int  jump length */
                    905: #define EXT_J  2       /* jump around sequence */
                    906: 
                    907: /*
                    908:  * Called at new pass or init. Returns 1 if another pass required.
                    909:  */
                    910: indPass()
                    911: {
                    912:        braCt = 0;              /* so far no branches */
                    913:        if (xpass) {
                    914:                xpass = 0;
                    915:                return (1);
                    916:        }
                    917:        return (0);
                    918: }
                    919: 
                    920: /*
                    921:  * Put out op code.
                    922:  */
                    923: static void
                    924: putOp(opCode)
                    925: register unsigned short opCode;
                    926: {
                    927:        if (opCode & 0xFF00) {
                    928:                outab(opCode >> 8);
                    929:                outab(opCode & 0xff);
                    930:        }
                    931:        else
                    932:                outab(opCode);
                    933: }
                    934: 
                    935: /*
                    936:  * Called for each relative branch.
                    937:  * Calculates branch size. Forces another pass if a branch expands.
                    938:  */
                    939: void
                    940: indBra(nearOp, byteOp, op)
                    941: unsigned short nearOp, byteOp;
                    942: register expr *op;
                    943: {
                    944:        static char *list;              /* one for each relative branch */
                    945:        static unsigned max;            /* size of list */
                    946:        char size;                      /* BYTE_J NEAR_J EXT_J */
                    947:        long d;                         /* displacment */
                    948:        short  flag, exref;
                    949:        char *old;
                    950: 
                    951:        /* insure space for branch data */
                    952:        if (max <= ++braCt)
                    953:                expand(&list, &max, 64, sizeof(char));
                    954: 
                    955:        old = list + (braCt - 1);
                    956:        /* assume size from last pass or shortest size for this jump. */
                    957:        size = pass ? *old : ((byteOp == NON_OP) ? NEAR_J : BYTE_J);
                    958: 
                    959:        if (NULL == op->ref)
                    960:                fatal("NULL address in relative branch"); /* TECH */
                    961: 
                    962:        flag = op->ref->flag;
                    963:        exref = 0; 
                    964: 
                    965:        if (flag & S_UNDEF) {   /* undefined symbol */
                    966:                if (pass)
                    967:                        size = NEAR_J;  /* known near */
                    968:                else if (BYTE_J == size)
                    969:                        xpass = 1;
                    970: 
                    971:                if (gswitch)    /* -g turns undefined to global */
                    972:                        exref = 1;
                    973:        }
                    974: 
                    975:        else if ((flag & S_EXREF) || (dot.sg != op->ref->sg)) {
                    976:                exref = 1;
                    977:                size = NEAR_J;          /* known near */
                    978:        }
                    979: 
                    980:        else if (BYTE_J == size) {
                    981:                /* Calculate displacment from end of byte instr */
                    982:                d = op->exp - (dot.loc + ((byteOp & 0xFF00) ? 3 : 2));
                    983: 
                    984:                if ((d < -128) || (d > 127))    /* near limits */
                    985:                        size = NEAR_J;
                    986:        }
                    987: 
                    988:        /* near branch and none available build jumpover */
                    989:        if ((NEAR_J == size) && (NON_OP == nearOp))
                    990:                size = EXT_J;
                    991: 
                    992:        /* How does this compare to the last time? */
                    993:        if (*old != size) {
                    994:                switch(pass) {
                    995:                case 1:
                    996:                        if (*old > size)        /* never shrink */
                    997:                                break;
                    998:                        xpass = 1;              /* take one more pass */
                    999:                case 0:
                   1000:                        *old = size;            /* take new size */
                   1001:                        break;
                   1002:                default:
                   1003:                        if (*old < size)        /* too late for changes */
                   1004:                                fatal("Internal error relative branch logic");
                   1005:                                 /* TECH */
                   1006:                }
                   1007:        }
                   1008: 
                   1009:        /* output code */
                   1010:        switch(*old) {
                   1011:        case BYTE_J:    /* short op */
                   1012:                putOp(byteOp);
                   1013:                if (exref)
                   1014:                        outrb(op, 1);
                   1015:                else
                   1016:                        outab((int)d);
                   1017:                break;
                   1018: 
                   1019:        case EXT_J:     /* jump around sequence */
                   1020:                putOp(byteOp);          /* caller's jump over byte jump */
                   1021:                outab(2);
                   1022: 
                   1023:                outab(JMP_SHORT);       /* byte jump over near jump */
                   1024:                outab(longMode ? 0x05 : 0x03);
                   1025: 
                   1026:                nearOp = JMP_NEAR;      /* near jump to caller's destination */
                   1027: 
                   1028:        case NEAR_J:    /* near jumps */
                   1029:                putOp(nearOp);
                   1030:                if (longMode)
                   1031:                        if (exref)
                   1032:                                outrl(op, 1);
                   1033:                        else    /* displacement from end of address */
                   1034:                                outal(op->exp - (dot.loc + 4));
                   1035:                else
                   1036:                        if (exref)
                   1037:                                outrw(op, 1);
                   1038:                        else    /* displacement from end of address */
                   1039:                                outaw((int)(op->exp - (dot.loc + 2)));
                   1040:        }
                   1041: }

unix.superglobalmegacorp.com

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