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

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

unix.superglobalmegacorp.com

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