Annotation of coherent/b/bin/c/n2/i386/asm.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * n2/i386/asm.c
                      3:  * The routines in this file assemble buffered code
                      4:  * and write the code to the output file.
                      5:  * i386.
                      6:  */
                      7: 
                      8: #ifdef   vax
                      9: #include "INC$LIB:cc2.h"
                     10: #else
                     11: #include "cc2.h"
                     12: #endif
                     13: 
                     14: #define        W       0x01                    /* W (word) bit */
                     15: #define        D       0x02                    /* D (direction) bit */
                     16: #define        ESC_2B  0x0F                    /* Two-byte op escape */
                     17: #define        ESC     0xD8                    /* Escape */
                     18: #define        WAIT    0x9B                    /* Wait */
                     19: 
                     20: static ADDRESS pc;                     /* Current assembly pc */
                     21: static ADDRESS pcdot[NSEG];            /* Working copy of seg '.' fields */
                     22: static int     pcseg;                  /* Current segment */
                     23: static int     pass;                   /* Pass flag; only 1 emits code */
                     24: 
                     25: extern int     hasfloat;               /* function uses floating point */
                     26: 
                     27: /*
                     28:  * Driving routine.
                     29:  * Run pass 0 of the assembly to get sizes.
                     30:  * All jumps are assumed to be short.
                     31:  * Fix up any that don't reach.
                     32:  * Run the second assembly pass to generate the final code.
                     33:  */
                     34: genfunc()
                     35: {
                     36:        register INS    *ip1, *ip2;
                     37:        register int    i;
                     38: 
                     39:        pc = dot;
                     40:        pass = 0;
                     41:        pcseg = dotseg;
                     42:        for (i = 0; i < NSEG; ++i)
                     43:                pcdot[i] = seg[i].s_dot;
                     44:        ip1 = ins.i_fp;
                     45:        while (ip1 != &ins) {
                     46:                assemble(ip1);
                     47:                ip1 = ip1->i_fp;
                     48:        }
                     49:        sdi();
                     50:        pc = dot;
                     51:        pass = 1;
                     52:        pcseg = dotseg;
                     53:        for (i = 0; i < NSEG; ++i)
                     54:                pcdot[i] = seg[i].s_dot;
                     55:        ip1 = ins.i_fp;
                     56:        while (ip1 != &ins) {
                     57:                asmdbgt(ip1);
                     58:                if (isvariant(VASM))
                     59:                        unassemble(ip1);
                     60:                else
                     61:                        assemble(ip1);
                     62:                ip2 = ip1->i_fp;
                     63:                free((char *) ip1);
                     64:                ip1 = ip2;
                     65:        }
                     66:        asmdbgt(&ins);
                     67: }
                     68: 
                     69: /*
                     70:  * Generate code for a single instruction.
                     71:  * Used to compile external data definitions, etc.
                     72:  */
                     73: genins(ip) register INS *ip;
                     74: {
                     75:        register int    i;
                     76: 
                     77:        for (pass=0; pass!=2; ++pass) {
                     78:                pc = dot;
                     79:                pcseg = dotseg;
                     80:                for (i = 0; i < NSEG; ++i)
                     81:                        pcdot[i] = seg[i].s_dot;
                     82:                if (isvariant(VASM) && pass != 0) {
                     83:                        if (ip->i_type != LINE
                     84:                        || isvariant(VLINES))
                     85:                                unassemble(ip);
                     86:                } else
                     87:                        assemble(ip);
                     88:        }
                     89: }
                     90: 
                     91: /*
                     92:  * This function fixes up the span dependent instructions.
                     93:  * The only case on the iAPX-86 is the jump, which has limited range.
                     94:  * There is nothing to be done with the adjustable displacements,
                     95:  * bacause these are always absolute and do not change.
                     96:  * For the moment,
                     97:  * unconditional JMP gets bumped from JMP i8 to JMP i32 (2 bytes -> 5);
                     98:  * conditional Jcc gets bumped from Jcc i8 to Jcc i32 (2 -> 6).
                     99:  * The 16-bit forms using operand escape prefix are probably better.
                    100:  */
                    101: sdi()
                    102: {
                    103:        register INS    *ip1, *ip2;
                    104:        register SYM    *sp;
                    105:        register int    bump, changes;
                    106:        SIGNEDADDRESS   disp;
                    107: 
                    108:        do {
                    109:                changes = 0;
                    110:                ip1 = ins.i_fp;
                    111:                while (ip1 != &ins) {
                    112:                        if (isoptjump(ip1)) {
                    113:                                if ((sp=ip1->i_sp) == NULL)
                    114:                                        cbotch("sdi");
                    115:                                if (ip1->i_pcseg != sp->s_seg)
                    116:                                        cbotch("x seg #1");
                    117:                                disp = sp->s_value-ip1->i_pc-2;
                    118:                                if (disp < -128 || disp > 127) {
                    119:                                        ip1->i_long = 1;
                    120:                                        changes = 1;
                    121:                                        bump = 3;
                    122:                                        if (ip1->i_rel != ZJMP)
                    123:                                                bump = 4;
                    124:                                        ip2 = ip1->i_fp;
                    125:                                        while (ip2 != &ins) {
                    126:                                                sdibump(ip1, ip2, bump);
                    127:                                                ip2 = ip2->i_fp;
                    128:                                        }
                    129:                                }
                    130:                        }
                    131:                        ip1 = ip1->i_fp;
                    132:                }
                    133:        } while (changes);
                    134: }
                    135: 
                    136: /*
                    137:  * This routine performs the nitty gritty
                    138:  * of bumping an instruction to a higher address because
                    139:  * an sdi changed from short to long.
                    140:  * The 'ip1' argument is a pointer to the INS of the jump.
                    141:  * The 'ip2' argument is the node to be bumped by 'bump' bytes.
                    142:  * Only labels and code in the same segment as the 'ip1' node are adjusted.
                    143:  */
                    144: sdibump(ip1, ip2, bump) register INS *ip1, *ip2; int bump;
                    145: {
                    146:        register int    type;
                    147:        register SYM    *sp;
                    148: 
                    149:        if ((type=ip2->i_type) == LLABEL) {
                    150:                if ((sp=ip2->i_sp) == NULL)
                    151:                        cbotch("sdibump");
                    152:                if (sp->s_seg == ip1->i_pcseg)
                    153:                        sp->s_value += bump;
                    154:        } else if (type==JUMP || type==CODE) {
                    155:                if (ip2->i_pcseg == ip1->i_pcseg)
                    156:                        ip2->i_pc += bump;
                    157:        }
                    158: }
                    159: 
                    160: /*
                    161:  * This routine checks if a node is an optimizable short jump.
                    162:  * The node must be a jump,
                    163:  * it must be short and it must either be the unconditional
                    164:  * jump or one of the jumps that has a reverse.
                    165:  */
                    166: isoptjump(ip1) register INS *ip1;
                    167: {
                    168:        register int    rel;
                    169: 
                    170:        if (ip1->i_type==JUMP && ip1->i_long==0) {
                    171:                rel = ip1->i_rel;
                    172:                if (rel!=ZJCXZ && rel!=ZLOOP && rel!=ZLOOPE && rel!=ZLOOPNE)
                    173:                        return 1;
                    174:        }
                    175:        return 0;
                    176: }
                    177: 
                    178: /*
                    179:  * Assemble a line.
                    180:  * If pass 1 the binary goes straight out.
                    181:  * The ip1 argument points to the INS node that is to be assembled. 
                    182:  */
                    183: assemble(ip1) register INS *ip1;
                    184: {
                    185:        SIGNEDADDRESS   disp;
                    186:        int     opbits, opcode, ostyle, prefix, m1, m2, m3, regm, rn, shortflag;
                    187:        int     align, count;
                    188:        sizeof_t length;
                    189:        OPINFO  *opinfop;
                    190:        SYM     *sp;
                    191:        AFIELD  a1;
                    192:        int     is16bit;                /* Current op needs 16-bit prefix */
                    193: 
                    194:        switch (ip1->i_type) {
                    195: 
                    196:        case ENTER:
                    197:                pcdot[pcseg] =  pc;
                    198:                pcseg = ip1->i_seg;
                    199:                pc =  pcdot[pcseg];
                    200:                if (pass != 0)
                    201:                        genseg(pcseg);
                    202:                break;
                    203: 
                    204:        case BLOCK:
                    205:                if ((length=ip1->i_len) != 0) {
                    206:                        if (pcseg == SBSS) {
                    207:                                pc += length;
                    208:                                if (pass != 0)
                    209:                                        dot += length;
                    210:                        } else if (pass != 0)
                    211:                                outnzb(length, 0);
                    212:                }
                    213:                break;
                    214: 
                    215:        case ALIGN:
                    216:                if ((align = ip1->i_align) != 0 && (pc & (align-1)) != 0) {
                    217:                        count = align - (pc & (align-1));
                    218:                        if (pcseg == SBSS) {
                    219:                                pc += count;
                    220:                                if (pass != 0)
                    221:                                        dot += count;
                    222:                        } else {
                    223:                                while (count--)
                    224:                                        asmab(0);
                    225:                        }
                    226:                }
                    227:                break;
                    228: 
                    229:        case JUMP:
                    230:                ip1->i_pc = pc;
                    231:                ip1->i_pcseg = pcseg;
                    232:                if ((sp=ip1->i_sp) == NULL) {
                    233:                        sp = llookup(ip1->i_labno, 0);
                    234:                        ip1->i_sp = sp;
                    235:                }
                    236:                if (pass != 0) {
                    237:                        if (sp==NULL || (sp->s_flag&S_DEF)==0)
                    238:                                cbotch("undef");
                    239:                        if (ip1->i_long == 0) { 
                    240:                                if (sp->s_seg != ip1->i_pcseg)
                    241:                                        cbotch("x seg #2");
                    242:                                disp = sp->s_value - pc - 2;
                    243:                                if (disp < -128 || disp > 127)
                    244:                                        cbotch("reach, disp=%d", disp);
                    245:                        }
                    246:                }
                    247:                opbits = opinfo[ip1->i_rel].op_opcode;
                    248:                if (ip1->i_long == 0) {
                    249:                        /* Short JMP or Jcc, i8 displacement. */
                    250:                        asmab(opbits);
                    251:                        asmab(disp);
                    252:                } else {
                    253:                        /* Long jumps, see comments on sdi() above. */
                    254:                        if (ip1->i_rel != ZJMP) {
                    255:                                /* Jcc i8 becomes Jcc i32. */
                    256:                                disp = sp->s_value - pc - 6;
                    257:                                asmab(ESC_2B);          /* 2-byte escape */
                    258:                                asmab(opbits+0x10);     /* 7x becomes 8x */
                    259:                                asmal(disp);
                    260:                                break;
                    261:                        }
                    262:                        disp = sp->s_value - pc - 5;
                    263:                        asmab(0xE9);                    /* Jump i32 */
                    264:                        asmal(disp);
                    265:                }
                    266:                break;
                    267: 
                    268:        case LLABEL:
                    269:                if ((sp=ip1->i_sp) == NULL) {
                    270:                        sp = llookup(ip1->i_labno, 1);
                    271:                        ip1->i_sp = sp;
                    272:                }
                    273:                sp->s_seg = pcseg;
                    274:                sp->s_value = pc;
                    275:                break;
                    276: 
                    277:        case LLLINK:
                    278:                if ((sp=ip1->i_sp) == NULL) {
                    279:                        sp = llookup(ip1->i_labno, 0);
                    280:                        ip1->i_sp = sp;
                    281:                }
                    282:                if (pass!=0 && (sp==NULL || (sp->s_flag&S_DEF)==0))
                    283:                        cbotch("undef");
                    284:                a1.a_mode = A_DIR;
                    285:                a1.a_sp = sp;
                    286:                a1.a_value = 0;
                    287:                asmxl(&a1, 0);
                    288:                break;
                    289: 
                    290:        case CODE:
                    291:                ip1->i_pc = pc;
                    292:                ip1->i_pcseg = pcseg;
                    293:                opcode = ip1->i_op;
                    294:                opinfop = &opinfo[opcode];
                    295:                opbits = opinfop->op_opcode;
                    296:                if (opinfop->op_flag & OP_WORD) {
                    297:                        is16bit = 1;
                    298:                        asmab(0x66);            /* 16-bit operand prefix */
                    299:                } else
                    300:                        is16bit = 0;
                    301:                switch (ostyle = opinfop->op_style) {
                    302:        
                    303:                case OF_INH2:
                    304:                        asmab(opbits);
                    305:                        asmab(0x0A);
                    306:                        break;
                    307: 
                    308:                case OF_INH:
                    309:                        asmab(opbits);
                    310:                        break;
                    311:        
                    312:                case OF_PUSH:
                    313:                case OF_POP:
                    314:                        m1 = MOD(af_p(ip1, 0));
                    315:                        rn = REGM(af_p(ip1, 0));
                    316:                        if ((ostyle == OF_PUSH) && (m1 == A_IMM)) {
                    317:                                if (isimmbyte(af_p(ip1, 0))) {
                    318:                                        asmab(0x6A);
                    319:                                        asmxb(af_p(ip1, 0), 0);
                    320:                                } else if (!is16bit) {
                    321:                                        asmab(0x68);
                    322:                                        asmxl(af_p(ip1, 0), 0);
                    323:                                } else {
                    324:                                        asmab(0x68);
                    325:                                        asmxw(af_p(ip1, 0), 0);
                    326:                                }
                    327:                                break;
                    328:                        }
                    329:                        if (m1 == A_DR || m1 == A_WR) {
                    330:                                asmab((ostyle == OF_PUSH) ? 0x50 | rn
                    331:                                                          : 0x58 | rn);
                    332:                                break;
                    333:                        }
                    334:                        if (ostyle == OF_PUSH)
                    335:                                asmgen(0xFF, 0x30, af_p(ip1, 0));
                    336:                        else
                    337:                                asmgen(0x8F, 0x00, af_p(ip1, 0));
                    338:                        break;
                    339:        
                    340:                case OF_SHR:
                    341:                        prefix = 0xD0 | (opbits&W);
                    342:                        opbits &= ~W;
                    343:                        if (ip1->i_af[1].a_mode == A_RCL)
                    344:                                prefix |= 0x02;
                    345:                        else if ((MOD(af_p(ip1, 1))) != A_IMM
                    346:                             ||   ip1->i_af[1].a_sp != NULL)
                    347:                                aerr(ip1);
                    348:                        disp = ip1->i_af[1].a_value;
                    349:                        if ((ip1->i_af[1].a_mode != A_RCL) && (disp != 1)) {
                    350:                                /* 286 shift immediate */
                    351:                                prefix &= 0xEF; /* Change 0xD0|W to 0xC0|W */
                    352:                                asmgen(prefix, opbits, af_p(ip1, 0));
                    353:                                asmab(disp);
                    354:                                break;
                    355:                        }
                    356:                        asmgen(prefix, opbits, af_p(ip1, 0));
                    357:                        break;
                    358:        
                    359:                case OF_ICALL:
                    360:                        asmgen(0xFF, opbits, af_p(ip1, 0));
                    361:                        break;
                    362:        
                    363:                case OF_CALL:
                    364:                        if ((MOD(af_p(ip1, 0))) != A_DIR)
                    365:                                aerr(ip1);
                    366:                        asmab(0xE8);
                    367:                        asmxl(af_p(ip1, 0), 1);
                    368:                        break;
                    369: 
                    370:                case OF_XCALL:
                    371:                        if ((MOD(af_p(ip1, 0))) != A_DIR)
                    372:                                aerr(ip1);
                    373:                        asmab(0x9A);
                    374:                        asmxl(af_p(ip1, 0), 0);
                    375:                        break;
                    376: 
                    377:                case OF_DOPS:
                    378:                case OF_DOP:
                    379:                        m1 = MOD(af_p(ip1, 0));
                    380:                        m2 = MOD(af_p(ip1, 1));
                    381:                        if (m2 == A_IMM) {
                    382:                                /*
                    383:                                 * Immediate right operand.
                    384:                                 * Use the special EAX etc. form if possible,
                    385:                                 * but not for byte immediate operands,
                    386:                                 * where the byte immediate form is better.
                    387:                                 */
                    388:                                shortflag = (ostyle == OF_DOPS) && isimmbyte(af_p(ip1, 1));
                    389:                                if (isEAX(af_p(ip1, 0))
                    390:                                 && (!shortflag || opbits == 0x84 || opbits == 0x85)) {
                    391:                                        /* Left operand is EAX, AX or AL. */
                    392:                                        if (opbits == 0x85)
                    393:                                                opbits = 0xA9;  /* test */
                    394:                                        else if (opbits == 0x84)
                    395:                                                opbits = 0xA8;  /* testb */
                    396:                                        else
                    397:                                                opbits |= 0x04; /* use EAX form */
                    398:                                        asmab(opbits);
                    399:                                } else {
                    400:                                        /*
                    401:                                         * Left operand is not EAX, AX or AL,
                    402:                                         * or (right operand is byte immediate
                    403:                                         * and operator is not TEST).
                    404:                                         */
                    405:                                        if (opbits==0x84 || opbits==0x85) {
                    406:                                                regm = 0;
                    407:                                                if (opbits == 0x84)
                    408:                                                        opbits = 0xF6;  /* test */
                    409:                                                else
                    410:                                                        opbits = 0xF7;  /* testb */
                    411:                                        } else {
                    412:                                                regm = opbits & 0x38;
                    413:                                                opbits = (opbits&W)|0x80;
                    414:                                                if (shortflag)
                    415:                                                        opbits |= 0x02;
                    416:                                        }
                    417:                                        asmgen(opbits, regm, af_p(ip1, 0));
                    418:                                }
                    419:                                if (shortflag || (opbits&W)==0)
                    420:                                        asmxb(af_p(ip1, 1), 0);
                    421:                                else if (!is16bit)
                    422:                                        asmxl(af_p(ip1, 1), 0);
                    423:                                else
                    424:                                        asmxw(af_p(ip1, 1), 0);
                    425:                                break;
                    426:                        }
                    427:                        /* To reg */
                    428:                        if (m1==A_DR || m1==A_BR || m1==A_WR) {
                    429:                                /* Test[b] */
                    430:                                if (opbits!=0x84 && opbits!=0x85)
                    431:                                        opbits |= 0x02; /* D */
                    432:                                asmgen(opbits, (REGM(af_p(ip1, 0)))<<3,
                    433:                                        af_p(ip1, 1));
                    434:                                break;
                    435:                        }
                    436:                        /* To mem */
                    437:                        asmgen(opbits, (REGM(af_p(ip1, 1)))<<3,
                    438:                                af_p(ip1, 0));
                    439:                        break;
                    440: 
                    441:                case OF_MUL3:
                    442:                        m1 = MOD(af_p(ip1, 0));
                    443:                        m2 = MOD(af_p(ip1, 1));
                    444:                        m3 = MOD(af_p(ip1, 2));
                    445:                        if ((m1 != A_DR && m1 != A_WR) || m3 != A_IMM)
                    446:                                aerr(ip1);
                    447:                        shortflag = 0;
                    448:                        if (isimmbyte(af_p(ip1, 2))) {
                    449:                                shortflag = 1;
                    450:                                opbits |= 0x02; /* Change 0x69 to 0x6B */
                    451:                        }
                    452:                        asmgen(opbits, (REGM(af_p(ip1, 0)))<<3, af_p(ip1, 1));
                    453:                        if (shortflag)
                    454:                                asmxb(af_p(ip1, 2), 0);
                    455:                        else if (!is16bit)
                    456:                                asmxl(af_p(ip1, 2), 0);
                    457:                        else
                    458:                                asmxw(af_p(ip1, 2), 0);
                    459:                        break;
                    460: 
                    461:                case OF_SOP:
                    462:                        m1 = MOD(af_p(ip1, 0));
                    463:                        prefix = ((opbits < 0x10)?0xFE:0xF6) | (opbits&W);
                    464:                        opbits &= ~W;
                    465:                        if (prefix==0xFF && (m1==A_DR || m1==A_WR)) {
                    466:                                asmab(0x40 | opbits |
                    467:                                        (REGM(af_p(ip1, 0))));
                    468:                                break;
                    469:                        }
                    470:                        asmgen(prefix, opbits, af_p(ip1, 0));
                    471:                        break;
                    472:        
                    473:                case OF_LEA:
                    474:                        m1 = MOD(af_p(ip1, 0));
                    475:                        m2 = MOD(af_p(ip1, 1));
                    476:                        if (m1!=A_DR || (m2!=A_DIR && m2!=A_XB))
                    477:                                aerr(ip1);
                    478:                        asmgen(opbits, (REGM(af_p(ip1, 0)))<<3,
                    479:                                af_p(ip1, 1));
                    480:                        break;
                    481:        
                    482:                case OF_MOV:
                    483:                        m1 = MOD(af_p(ip1, 0));
                    484:                        m2 = MOD(af_p(ip1, 1));
                    485:                        /* Sanity check: register specs vs. opcode. */
                    486:                        opcode = ip1->i_op;
                    487: #if    1
                    488:                        /*
                    489:                         * Kludge flakey register references generated
                    490:                         * by the load table in n1/i386/tables/leaves.t.
                    491:                         * There must be a better way.
                    492:                         */
                    493:                        if ((opcode == ZMOVW && m2 == A_DR)
                    494:                         || (opcode == ZMOVB && (m2 == A_WR || m2 == A_DR))) {
                    495:                                ip1->i_af[1].a_mode &= ~A_AMOD;
                    496:                                ip1->i_af[1].a_mode |= (opcode == ZMOVW) ? A_WR : A_BR;
                    497:                                m2 = MOD(af_p(ip1, 1));
                    498:                        }
                    499: #endif
                    500:                        if (((opcode != ZMOV ) && ((m1 == A_DR) || (m2 == A_DR)))
                    501:                         || ((opcode != ZMOVW) && ((m1 == A_WR) || (m2 == A_WR)))
                    502:                         || ((opcode != ZMOVB) && ((m1 == A_BR) || (m2 == A_BR))))
                    503:                                aerr(ip1);
                    504:                        if (m2 == A_IMM) {
                    505:                                /* Immediate moves. */
                    506:                                if (m1 == A_DR) {
                    507:                                        /* Immediate to dword register. */
                    508:                                        asmab(0xB8 |
                    509:                                                (REGM(af_p(ip1, 0))));
                    510:                                        asmxl(af_p(ip1, 1), 0);
                    511:                                        break;
                    512:                                } else if (m1 == A_BR) {
                    513:                                        /* Immediate to byte register. */
                    514:                                        asmab(0xB0 |
                    515:                                                (REGM(af_p(ip1, 0))));
                    516:                                        asmxb(af_p(ip1, 1), 0);
                    517:                                        break;
                    518:                                } else if (m1 == A_WR) {
                    519:                                        /* Immediate to word register. */
                    520:                                        asmab(0xB8 |
                    521:                                                (REGM(af_p(ip1, 0))));
                    522:                                        asmxw(af_p(ip1, 1), 0);
                    523:                                        break;
                    524:                                }
                    525:                                /* Immediate to memory. */
                    526:                                asmgen((0xC6 | (opbits&W)), 0, af_p(ip1, 0));
                    527:                                if ((opbits&W) == 0)
                    528:                                        asmxb(af_p(ip1, 1), 0);
                    529:                                else if (!is16bit)
                    530:                                        asmxl(af_p(ip1, 1), 0);
                    531:                                else
                    532:                                        asmxw(af_p(ip1, 1), 0);
                    533:                                break;
                    534:                        }
                    535:                        if (isEAX(af_p(ip1, 0)) && m2==A_DIR) {
                    536:                                /* Direct to AL, AX, or EAX. */
                    537:                                asmab(0xA0 | (opbits&W));
                    538:                                asmxl(af_p(ip1, 1), 0);
                    539:                                break;
                    540:                        }
                    541:                        if (m1==A_DIR && isEAX(af_p(ip1, 1))) {
                    542:                                /* AL, AX or EAX to direct. */
                    543:                                asmab(0xA2 | (opbits&W));
                    544:                                asmxl(af_p(ip1, 0), 0);
                    545:                                break;
                    546:                        }
                    547:                        if (m1==A_DR || m1==A_WR || m1==A_BR) {
                    548:                                /* To dword, word or byte register. */
                    549:                                asmgen(opbits|D,
                    550:                                        (REGM(af_p(ip1, 0)))<<3,
                    551:                                        af_p(ip1, 1));
                    552:                                break;
                    553:                        }
                    554:                        if (m2==A_DR || m2==A_WR || m2==A_BR) {
                    555:                                /* From dword, word or byte register. */
                    556:                                asmgen(opbits,
                    557:                                        (REGM(af_p(ip1, 1)))<<3,
                    558:                                        af_p(ip1, 0));
                    559:                                break;
                    560:                        }
                    561:                        aerr(ip1);
                    562:                        break;
                    563:        
                    564:                case OF_MUL:
                    565:                        prefix = 0xF6 | (opbits&W);
                    566:                        opbits &= ~W;
                    567:                        asmgen(prefix, opbits, af_p(ip1, 0));
                    568:                        break;
                    569:        
                    570:                case OF_WORD:
                    571:                case OF_BYTE:
                    572:                case OF_LONG:
                    573:                case OF_LPTR:
                    574:                case OF_GPTR:
                    575:                        if ((MOD(af_p(ip1, 0))) != A_DIR)
                    576:                                aerr(ip1);
                    577:                        if (ostyle == OF_BYTE)
                    578:                                asmxb(af_p(ip1, 0), 0);
                    579:                        else if (ostyle == OF_WORD)
                    580:                                asmxw(af_p(ip1, 0), 0);
                    581:                        else
                    582:                                asmxl(af_p(ip1, 0), 0);
                    583:                        break;
                    584: 
                    585:                case OF_2B:
                    586:                        /*
                    587:                         * movsxw and movzxw do not take 16-bit operand prefix,
                    588:                         * hence do not have OP_WORD set in optab.c;
                    589:                         * now tell asmgen the operand is a 16-bit object.
                    590:                         */
                    591:                        if ((opinfop->op_flag & OP_BYTE) == 0)
                    592:                                is16bit = 1;
                    593:                        m1 = MOD(af_p(ip1, 0));
                    594:                        m2 = MOD(af_p(ip1, 1));
                    595: #if    0
                    596:                        if (m1 != A_DR || m2 == A_DR
                    597:                         || (is16bit && m2 == A_BR)
                    598:                         || (!is16bit && m2 == A_WR))
                    599:                                aerr(ip1);
                    600: #else
                    601:                        if (m1 != A_DR)
                    602:                                aerr(ip1);
                    603:                        /*
                    604:                         * Kludge flakey register references generated
                    605:                         * by the widen table in n1/i386/tables/leaves.t.
                    606:                         * There must be a better way.
                    607:                         */
                    608:                        if (m2 == A_DR) {
                    609:                                ip1->i_af[1].a_mode &= ~A_AMOD;
                    610:                                ip1->i_af[1].a_mode |= (is16bit) ? A_WR : A_BR;
                    611:                        }
                    612: #endif
                    613:                        asmab(ESC_2B);
                    614:                        asmgen(opbits,
                    615:                                (REGM(af_p(ip1, 0)))<<3,
                    616:                                af_p(ip1, 1));
                    617:                        break;
                    618:                        
                    619:                /*
                    620:                 * 8087 or 80287 floating point operations.
                    621:                 * See comments preceding "asmfwait()" below.
                    622:                 */
                    623:                case OF_FWAIT:
                    624:                        asmfwait();
                    625:                        break;
                    626: 
                    627:                case OF_FD9:
                    628:                        asmfop(0xD9, 0);
                    629:                        asmab(opbits);
                    630:                        break;
                    631: 
                    632:                case OF_FDD:
                    633:                        asmfop(0xDD, 0);
                    634:                        asmab(opbits);
                    635:                        break;
                    636: 
                    637:                case OF_FDE:
                    638:                        asmfop(0xDE, 0);
                    639:                        asmab(opbits);
                    640:                        break;
                    641: 
                    642:                case OF_FRM:
                    643:                        asmfop(ESC | (opbits & 0x07), 0);
                    644:                        asmgen(-1, opbits&0x38, af_p(ip1, 0));
                    645:                        break;
                    646: 
                    647:                default:
                    648:                        cbotch("cannot assemble %d", opcode);
                    649:                }
                    650:        }
                    651: }
                    652: 
                    653: /*
                    654:  * Output an effective address.
                    655:  * Understands ModR/M byte and SIB and all that.
                    656:  * An opcode of -1 is a flag that says don't put
                    657:  * out the opcode and treat a register address field as an error.
                    658:  * It is used for the 8087.
                    659:  * The r field is preshifted left by 3 bits.
                    660:  */
                    661: asmgen(op, r, afp) int op, r; register AFIELD *afp;
                    662: {
                    663:        SIGNEDADDRESS   disp;
                    664:        int     mode, regm, sib, sibflag;
                    665: 
                    666:        if (op >= 0)
                    667:                asmab(op);
                    668:        mode = MOD(afp);
                    669:        regm = REGM(afp);
                    670:        if (mode==A_IMM)
                    671:                cbotch("asmgen op=%d r=%d mode=%d regm=%d",
                    672:                        op, r, mode, regm);
                    673:        else if (mode==A_DR || mode==A_BR || mode==A_WR) {
                    674:                /* Register: mod=11. */
                    675:                if (op < 0)
                    676:                        cbotch("asmgen");
                    677:                asmab(0xC0 | r | regm);
                    678:                return;
                    679:        } else if (mode == A_DIR) {
                    680:                /* Direct: mod=00, r/m=5, 32-bit displacement. */
                    681:                asmab(0x05 | r);
                    682:                asmxl(afp, 0);
                    683:                return;
                    684:        }
                    685:        /* Neither immediate nor register nor direct, must be symbol based or indexed. */
                    686:        sibflag = (mode == A_XSIB);
                    687:        if (sibflag) {
                    688:                regm = 4;                       /* r/m=4 indicates SIB present */
                    689:                sib = SIB(afp->a_mode);         /* extract SIB contents */
                    690:                if ((sib & A_REGM) == 5) {
                    691:                        /* SIB with no base, 32-bit displacement: mod=00. */
                    692:                        asmab(r | regm);
                    693:                        asmab(sib);
                    694:                        asmxl(afp, 0);
                    695:                        return;
                    696:                }
                    697:        }
                    698:        if (afp->a_sp == NULL) {
                    699:                /* Not symbol based. */
                    700:                disp = afp->a_value;
                    701:                if (disp == 0) {
                    702:                        /* No displacement, mod=00. */
                    703:                        if (regm != 5) {
                    704:                                asmab(r | regm);
                    705:                                if (sibflag)
                    706:                                        asmab(sib);
                    707:                                return;
                    708:                        }
                    709:                }
                    710:                if (disp >= -128 && disp <= 127) {
                    711:                        /* 8-bit displacement, mod=01. */
                    712:                        asmab(0x40 | r | regm);
                    713:                        if (sibflag)
                    714:                                asmab(sib);
                    715:                        asmab(disp);
                    716:                        return;
                    717:                }
                    718:                /* Fall through for 32-bit displacement... */
                    719:        }
                    720:        /*
                    721:         * Symbol based (always requires 4-byte value as relocation target)
                    722:         * or indexed with 32-bit displacement, mod=10.
                    723:         */
                    724:        asmab(0x80 | r | regm);
                    725:        if (sibflag)
                    726:                asmab(sib);
                    727:        asmxl(afp, 0);
                    728: }
                    729: 
                    730: /*
                    731:  * Output an absolute byte.
                    732:  * Toss the byte away if this is not the second pass.
                    733:  * Check for compiling code into the bss segment.
                    734:  */
                    735: asmab(b) int b;
                    736: {
                    737:        if (pass != 0) {
                    738:                berr();
                    739:                outab(b);
                    740:        }
                    741:        ++pc;
                    742: }
                    743: 
                    744: /*
                    745:  * Output an absolute word.
                    746:  * Toss the word away if this is not the second pass.
                    747:  * Check for compiling code into the bss segment.
                    748:  */
                    749: asmaw(w) int w;
                    750: {
                    751:        if (pass != 0) {
                    752:                berr();
                    753:                outaw(w);
                    754:        }
                    755:        pc += 2;
                    756: }
                    757: 
                    758: /*
                    759:  * Output an absolute dword (ival_t).
                    760:  * Toss the word away if this is not the second pass.
                    761:  * Check for compiling code into the bss segment.
                    762:  */
                    763: asmal(i) ival_t i;
                    764: {
                    765:        if (pass != 0) {
                    766:                berr();
                    767:                outal(i);
                    768:        }
                    769:        pc += 4;
                    770: }
                    771: 
                    772: /*
                    773:  * Output a general byte.
                    774:  * The 'afp' argument is a pointer to an 'afield'.
                    775:  * The 'flag' is true for pc relative addressing.
                    776:  */
                    777: asmxb(afp, flag) register AFIELD *afp; int flag;
                    778: {
                    779:        if (pass != 0) {
                    780:                berr();
                    781:                outxb(afp->a_sp, afp->a_value, flag);
                    782:        }
                    783:        ++pc;
                    784: }
                    785: 
                    786: /*
                    787:  * Output a general word.
                    788:  * The 'afp' parameter is a pointer to an 'afield'.
                    789:  * The 'flag' is true for pc relative addressing.
                    790:  */
                    791: asmxw(afp, flag) register AFIELD *afp; int flag;
                    792: {
                    793:        if (pass != 0) {
                    794:                berr();
                    795:                outxw(afp->a_sp, afp->a_value, flag);
                    796:        }
                    797:        pc += 2;
                    798: }
                    799: 
                    800: /*
                    801:  * Output a general word.
                    802:  * The 'afp' parameter is a pointer to an 'afield'.
                    803:  * The 'flag' is true for pc relative addressing.
                    804:  */
                    805: asmxl(afp, flag) register AFIELD *afp; int flag;
                    806: {
                    807:        if (pass != 0) {
                    808:                berr();
                    809:                outxl(afp->a_sp, afp->a_value, flag);
                    810:        }
                    811:        pc += 4;
                    812: }
                    813: 
                    814: /*
                    815:  * Notes on 8087 and 80287 opcode generation:
                    816:  * The 8086 does not check the coprocessor BUSY line when it encounters
                    817:  * a coprocessor escape (an 8087 opcode).
                    818:  * Therefore, an FWAIT must precede every 8087 opcode.
                    819:  * Sequences which require coprocessor synchronization
                    820:  * (e.g., awaiting completion of store from 8087 to 8086 memory)
                    821:  * can include explicit FWAITs which do not precede 8087 ops.
                    822:  * The 80286 checks its coprocessor BUSY line when it sees an 80287 opcode.
                    823:  * Therefore, the 80287 does not require an FWAIT before each 80287 opcode,
                    824:  * but explicit FWAITs are still required for synchronization.
                    825:  *
                    826:  * If EMUFIXUPS is true when the compiler is built,
                    827:  * the OMF output writer targets the FWAIT which precedes an 8087 opcode
                    828:  * with a magic "M:..." fixup;
                    829:  * this happens only in the OMF output writer n1/i8086/outomf.c.
                    830:  * The linker can then create objects which use either 8087 hardware
                    831:  * or software floating point emulation.  In the latter case, the
                    832:  * linker changes the 8087 instructions into traps to the emulator.
                    833:  *
                    834:  * If the compile-time variant VEMU87 is set,
                    835:  * the compiler writes "call emu87" before each 8087 opcode
                    836:  * and suppresses the leading FWAIT.
                    837:  * The emulator "emu87" can execute "fwait; ret" or replace "call emu87" with
                    838:  * "nop; nop; fwait" if an 8087 is actually present at runtime.
                    839:  */
                    840: 
                    841: /*
                    842:  * Output an explicit FWAIT opcode for the 8087.
                    843:  * The byte will be fiddled by an M:_WT fixup #if EMUFIXUPS.
                    844:  */
                    845: asmfwait()
                    846: {
                    847:        hasfloat = 1;
                    848: #if    0
                    849:        if (isvariant(VEMU87)) {
                    850:                asmemucall();           /* call emu87 */
                    851:                return;                 /* and suppress the FWAIT */
                    852:        }
                    853: #endif
                    854:        if (pass != 0) {
                    855:                berr();
                    856:                outfb(WAIT);
                    857:        }
                    858:        ++pc;
                    859: }
                    860: 
                    861: /*
                    862:  * Output an 8087 opcode for the 8087.
                    863:  * The "prefix" argument is just the A_PREFX code from the address.
                    864:  * The opcode will be preceded by an FWAIT if necessary,
                    865:  * and the FWAIT will be fiddled by an M:_W?S fixup #if EMUFIXUPS.
                    866:  */
                    867: asmfop(op, prefix)
                    868: {
                    869:        hasfloat = 1;
                    870: #if    0
                    871:        if (isvariant(VEMU87)) {
                    872:                asmemucall();           /* call emu87 */
                    873:                if (pass != 0)
                    874:                        outfb(op);      /* and suppress FWAIT */
                    875:                pc++;
                    876:                return;
                    877:        }
                    878: #endif
                    879:        if (pass != 0) {
                    880:                berr();
                    881:                outfb(op);      /* no FWAIT for 80x87 */
                    882:        }
                    883:        pc++;
                    884: }
                    885: 
                    886: #if    0
                    887: /*
                    888:  * Assemble a call to the IEEE software floating point 8087 emulator.
                    889:  */
                    890: asmemucall(){
                    891:        if (pass != 0) {
                    892:                berr();
                    893:                outemucall();
                    894:        }
                    895:        pc += 5;
                    896: }
                    897: 
                    898: /*
                    899:  * Output a call to the 8087 emulator.
                    900:  * Called from above and from genepilog (for FWAIT in epilog).
                    901:  */
                    902: outemucall()
                    903: {
                    904:        static SYM *emu87p;
                    905: 
                    906:        if (emu87p == NULL)
                    907:                emu87p = glookup("emu87", 0);
                    908:        outab(0x9A);                    /* far call */
                    909:        outxl(emu87p, 0, 0);            /* offset, absolute */
                    910: }
                    911: #endif
                    912: 
                    913: /* Oops. */
                    914: aerr(ip1) register INS *ip1;
                    915: {
                    916:        register SYM    *sp;
                    917:        register int    i;
                    918: 
                    919:        printf("aerr: op=%d\n", ip1->i_op);
                    920:        for (i = 0; i < ip1->i_naddr; ++i) {
                    921:                printf("Operand %d:", i);
                    922:                printf(" mode=%04x", ip1->i_af[i].a_mode);
                    923:                printf(" offs=%d",  ip1->i_af[i].a_value);
                    924:                if ((sp=ip1->i_af[i].a_sp) != NULL) {
                    925:                        if ((sp->s_flag&S_LABNO) != 0)
                    926:                                printf(" off L%d", sp->s_labno);
                    927:                        else
                    928:                                printf(" off %s", sp->s_id);
                    929:                }
                    930:                printf("\n");
                    931:        }
                    932:        cbotch("aerr");
                    933: }
                    934: 
                    935: /* BSS oops. */
                    936: berr()
                    937: {
                    938:        if (pcseg == SBSS)
                    939:                cbotch("bss");
                    940: }
                    941: 
                    942: /* Return true if afp represents AL, AX or EAX. */
                    943: isEAX(afp) register AFIELD *afp;
                    944: {
                    945:        register int mode;
                    946: 
                    947:        mode = afp->a_mode;
                    948:        return (mode==A_REAX || mode==A_RAX || mode==A_RAL);
                    949: }
                    950: 
                    951: /*
                    952:  * This routine returns true if the argument AFIELD is a valid byte immediate,
                    953:  * as used by the special s:w encoding on some instructions.
                    954:  * This lets the assembler write imm8 (sign-extended by i386) rather than
                    955:  * an imm32 or imm16.
                    956:  * The legality of the mode and the fact that
                    957:  * the AFIELD is an immediate have already been checked.
                    958:  */
                    959: isimmbyte(afp) register AFIELD *afp;
                    960: {
                    961:        register ADDRESS value;
                    962: 
                    963:        if (afp->a_sp == NULL) {
                    964:                value = afp->a_value & 0xFFFFFF80L;     /* top 25 bits */
                    965:                if (value==0xFFFFFF80L || value==0L)
                    966:                        return 1;
                    967:        }
                    968:        return 0;
                    969: }
                    970: 
                    971: /* end of n2/i386/asm.c */

unix.superglobalmegacorp.com

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