i86esc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 726 行 · 第 1/2 页

C
726
字号
            }
        } else {
            f = F_OFFSET;
            rel = TRUE;
            if( ( class & GET_BASE ) == OC_CALL ) {
                _OutCNear;
            } else {
                _OutJNear;
            }
        }
        OutCodeDisp( lbl, f, rel, class );
    }
}


static  void    OutShortDisp( label_handle lbl ) {
/************************************************/

    offset              addr;

    addr = AskAddress( lbl );
    if( addr == ADDR_UNKNOWN ) {
        OutPatch( lbl, _SHORT_PATCH );
        addr = 0;
    }
    _OutShortD( addr );
}


static  void    OutCodeDisp( label_handle lbl, fix_class f,
                             bool rel, oc_class class ) {
/********************************************************/

    offset              addr;
    sym_handle          sym;

    sym = AskForLblSym( lbl );
    if( AskIfRTLabel( lbl ) ) {
        OutRTImport( (int)sym, f );
        if( class & ATTR_FAR ) {
            _OutFarD( 0, 0 );
        } else {
            _OutFarOff( 0 );
        }
    } else if( AskIfCommonLabel( lbl ) ) {
        OutSpecialCommon( (int)sym, f, rel );
        _OutFarOff( 0 );
    } else if( sym != NULL && UseImportForm( FEAttr( sym ) ) ) { /* 90-05-22 */
        OutImport( sym, f, rel );
        if( class & ATTR_FAR ) {
            _OutFarD( 0, 0 );
        } else {
            _OutFarOff( 0 );
        }
    } else {                /* patch, to be done later*/
        addr = AskAddress( lbl );
        if( ( class & ATTR_FAR ) == 0 ) {
            if( addr == ADDR_UNKNOWN ) {
                OutPatch( lbl, _NEAR_PATCH );
                addr = 0;
            }
            _OutNearD( addr );
        } else {
            if( addr == ADDR_UNKNOWN ) {
                OutPatch( lbl, _OFFSET_PATCH );
            }
            _OutFarOff( addr );
            OutReloc( AskSegID( sym, CG_FE ), F_BASE, FALSE );
            _OutFarSeg( 0 );
        }
    }
}


static  label_handle    ExpandObj( byte *cur, int explen ) {
/**********************************************************/

    byte               *fini;
    byte                key;
    label_handle        lbl;
    sym_handle          sym;
    offset              val = 0;
    seg_id              seg;
    fix_class           class;
    bool                rel;
    int                 len;

    lbl = NULL;
    fini = cur + explen;
    while( cur < fini ) {
        len = 0;
        while( cur[len] != ESC ) {
            ++len;
            if( cur + len >= fini ) break;
        }
        if( len != 0 ) {
            OutDBytes( len, cur );
            cur += len;
            if( cur >= fini ) break;
        }
        cur++;
        key = *cur++;
        if( key == ESC ) {
            OutDataByte( ESC );
            continue;
        }
        if( key & BASE ) {
            class = F_BASE;
        } else if( key & LDOF ) {
            class = F_LDR_OFFSET;
        } else {
            class = F_OFFSET;
        }
        if( key & SELF ) {
            rel = TRUE;
        } else {
            rel = FALSE;
        }
        switch( key & ~MASK ) {
        case REL:
            seg = *(seg_id *)cur;
            cur += sizeof( seg_id );
            OutReloc( seg, class, rel );
            val = 0;
            break;
        case SYM:          /* never BASE*/
            sym = *(pointer *)cur;
            cur += sizeof( pointer );
            lbl = AskForSymLabel( sym, CG_FE );
            val = AskAddress( lbl );
            if( val == ADDR_UNKNOWN ) {
                if( class == F_OFFSET || class == F_LDR_OFFSET ) {
                    OutPatch( lbl, ADD_PATCH | _OFFSET_PATCH );
                } else {
                    OutPatch( lbl, ADD_PATCH | WORD_PATCH );
                }
                val = 0;
            }
            OutReloc( AskSegID( sym, CG_FE ), class, rel );
            break;
        case LBL:          /* never BASE*/
            seg = *(seg_id *)cur;
            cur += sizeof( seg_id );
            lbl = *(pointer *)cur;
            cur += sizeof( pointer );
            if( AskIfRTLabel( lbl ) ) {
                OutRTImportRel( (int)AskForLblSym( lbl ), F_OFFSET, FALSE );
                val = 0;
            } else {
                if( AskIfCommonLabel( lbl ) ) {
                    OutSpecialCommon( (int)AskForLblSym( lbl ), class, rel );
                } else {
                    OutReloc( seg, class, rel );
                }
                val = AskAddress( lbl );
                if( val == ADDR_UNKNOWN ) {
                    if( class == F_OFFSET || class == F_LDR_OFFSET ) {
                        OutPatch( lbl, ADD_PATCH | _OFFSET_PATCH );
                    } else {
                        OutPatch( lbl, ADD_PATCH | WORD_PATCH );
                    }
                    val = 0;
                }
            }
            break;
        case IMP:
            OutImport( *(sym_handle *)cur, class, rel );
            cur += sizeof( sym_handle * );
            val = 0;
            break;
        case ABS:
            val = *cur;
            cur++;
            OutAbsPatch( *(pointer *)cur, val );
            cur += sizeof( pointer );
            continue;
        case FUN:
            OutFPPatch( *cur );
            cur++;
            continue;
        default:
            _Zoiks( ZOIKS_038 );
            break;
        }
        if( key & OFST ) {
            val += *(offset *)cur;
            cur += sizeof( offset );
        }
        if( class == F_BASE ) {
            _OutFarSeg( val );
        } else if ( class == F_OFFSET || class == F_LDR_OFFSET ) {
            _OutFarOff( val );          /* offset*/
        } else if( class == F_PTR ) {
            _OutFarOff( val );
            _OutFarSeg( 0 );        /* segment*/
        }
    }
    return( lbl );
}

extern  void    OutputOC( any_oc *oc, any_oc *next_lbl ) {
/********************************************************/

    label_handle        lbl;
    sym_handle          sym;
    oc_class            base;
    int                 len;
    offset              lc;
    byte                *ptr;

    base = oc->oc_entry.class & GET_BASE;
    if( base != OC_LABEL ) {
        DumpSavedDebug();
    }
    SetUpObj( FALSE );
    switch( base ) {
    case OC_CODE:
    case OC_DATA:
        ExpandObj( oc->oc_entry.data, oc->oc_entry.reclen-sizeof(oc_header) );
        break;
    case OC_IDATA:
        if( next_lbl != NULL ) { /* cause next_lbl to need no alignment */
            len = -( AskLocation() + oc->oc_entry.objlen );
            len &= next_lbl->oc_entry.objlen;
            DoAlignment( len );
        }
        OutSelect( TRUE );
        SendBytes( &oc->oc_entry.data[ 0 ], oc->oc_entry.objlen );
        OutSelect( FALSE );
        break;
    case OC_BDATA:
        SendBytes( &oc->oc_entry.data[ 0 ], oc->oc_entry.objlen );
        break;
    case OC_LABEL:
        /* figure out number of bytes to pad */
        lc = AskLocation();
        len = -lc & oc->oc_entry.objlen;
        if( AskIfUniqueLabel( oc->oc_handle.handle ) ) {
            if( (lc == LastUnique) && (len == 0) ) {
                /* Two unique labels have ended up next to each other.
                   Pad out to next label alignment boundry. */
                len = oc->oc_entry.objlen + 1;
            }
            LastUnique = lc + len;
        }
        DoAlignment( len );
        OutLabel( oc->oc_handle.handle );           /* do patches*/
        DbgSetBase();
        DumpSavedDebug();
        break;
    case OC_LREF:
        lbl = oc->oc_handle.handle;
        sym = AskForLblSym( lbl );
        if( AskIfRTLabel( lbl ) ) {
            OutRTImport( (int)sym, F_OFFSET );
            lc = 0;
        } else if( AskIfCommonLabel( lbl ) ) {
            OutSpecialCommon( (int)sym, F_OFFSET, FALSE );
            lc = 0;
        } else if( sym != NULL && UseImportForm( FEAttr( sym ) ) ) {
            OutImport( sym, F_OFFSET, FALSE );
            lc = 0;
        } else {
            OutReloc( AskOP(), F_OFFSET, FALSE );
            lc = AskAddress( lbl );
            if( lc == ADDR_UNKNOWN ) {
                OutPatch( lbl, ADD_PATCH | _OFFSET_PATCH );
                lc = 0;
            }
        }
        _OutFarOff( lc );
        break;
    case OC_JMPI:
    case OC_CALLI:
    case OC_JCONDI:
        ptr = oc->oc_entry.data;
        len = 0;
        while( ptr[len] != M_CJINEAR ) {
            ++len; /* skip over top of any prefixes */
        }
        ++len;
        _OutOpndSize;
        ExpandObj( ptr, len );
        ptr += len;

    /* Need to put bits in 2nd byte of instruction distinguishing call vs.*/
    /* jump -- this is because the optimizer may change*/
    /* calls to jumps ...*/

        /* ASSUME RMR BYTE IS NOT DOUBLED BECAUSE OF ESCAPES*/
        if( base == OC_CALLI ) {
            *ptr |= B_IND_RMR_CALL;
        } else {
            *ptr |= B_IND_RMR_JMP;
        }
        OutDataByte( *ptr++ );
        lbl = ExpandObj( ptr, oc->oc_entry.reclen - sizeof(oc_header) - 1 - len );
        if( lbl != NULL && base == OC_JMPI ) {
            TellKeepLabel( lbl ); /* make sure label comes out*/
            GenKillLabel( lbl );  /* but kill it when it does*/
        }
        break;
    case OC_CALL:
    case OC_JMP:
    case OC_JCOND:
        ExpandCJ( oc );
        break;
    case OC_RET:
        _OutOpndSize;
        len = M_RET;
        if( oc->oc_entry.class & ATTR_FAR ) {
            len |= B_RET_LONG;
        }
        if( oc->oc_entry.class & ATTR_IRET ) {
            len |= B_RET_IRET;
        }
        if( oc->oc_entry.class & ATTR_POP ) {
            OutDataByte( len );
            OutDataInt( oc->oc_ret.pops );
        } else {
            OutDataByte( len | B_RET_NOPOP );
        }
        break;
    case OC_INFO:
        base = oc->oc_entry.class & INFO_MASK;
        switch( base ) {
        case INFO_LINE:
            OutLineNum( oc->oc_linenum.line, oc->oc_linenum.label_line );
            break;
        case INFO_LDONE:
            TellScrapLabel( oc->oc_handle.handle );
            break;
        case INFO_DEAD_JMP:
            _Zoiks( ZOIKS_036 );
            break;
        case INFO_DBG_RTN_BEG:
        case INFO_DBG_BLK_BEG:
        case INFO_DBG_EPI_BEG:
            SaveDbgOc = base;
            SaveDbgPtr = oc->oc_debug.ptr;
            break;
        case INFO_DBG_BLK_END:
            DbgBlkEnd( oc->oc_debug.ptr, AskLocation() );
            break;
        case INFO_DBG_PRO_END:
            DbgProEnd( oc->oc_debug.ptr, AskLocation() );
            break;
        case INFO_DBG_RTN_END:
            DbgRtnEnd( oc->oc_debug.ptr, AskLocation() );
            OutLineNum( 0, FALSE ); /* Kill pending line number */
            break;
        case INFO_SELECT:
            OutSelect( oc->oc_select.starts );
            break;
        }
        break;
    default :
        _Zoiks( ZOIKS_036 );
        break;
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?