i86esc.c

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

C
726
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "ocentry.h"
#include "escape.h"
#include "objrep.h"
#include "system.h"
#include "model.h"
#include "jumps.h"
#include "zoiks.h"
#include "fppatch.h"
#include "feprotos.h"

extern  void            DbgSetBase( void );
extern  void            OutAbsPatch(abspatch*,patch_attr);
extern  void            OutFPPatch(fp_patches);
extern  void            OutImport(sym_handle,fix_class,bool);
extern  void            OutRTImport(int,fix_class);
extern  void            OutRTImportRel(int,fix_class,bool rel);
extern  void            OutSelect(bool);
extern  bool            AskIfRTLabel(label_handle);
extern  sym_handle      AskForLblSym(label_handle);
extern  byte            ReverseCondition(byte);
extern  void            DbgRtnEnd(pointer,offset);
extern  void            DbgBlkEnd(pointer,offset);
extern  void            DbgEpiBeg(pointer,offset);
extern  void            DbgProEnd(pointer,offset);
extern  void            DbgBlkBeg(pointer,offset);
extern  void            DbgRtnBeg(pointer,offset);
extern  offset          AskLocation( void );
extern  void            TellScrapLabel(label_handle);
extern  void            OutLineNum( cg_linenum,bool);
extern  void            GenKillLabel(pointer);
extern  void            TellKeepLabel(label_handle);
extern  void            OutDataInt(int);
extern  void            OutDataLong(long);
extern  void            OutPatch(label_handle,patch_attr);
extern  void            OutReloc(seg_id,fix_class,bool);
extern  seg_id          AskOP( void );
extern  void            OutLabel(label_handle);
extern  void            OutDataByte(byte);
extern  void            OutDBytes(unsigned_32,byte*);
extern  void            SetUpObj(bool);
extern  offset          AskAddress(label_handle);
extern  label_handle    AskForSymLabel(pointer,cg_class);
extern  segment_id      AskSegID(pointer,cg_class);
extern  void            EmitOffset(offset);
extern  void            EmitPtr(pointer);
extern  abspatch        *NewAbsPatch( void );
extern  void            EmitByte(byte);
extern  void            EmitSegId(seg_id);
extern  void            InsertByte(byte);
extern  int             OptInsSize(oc_class,oc_dest_attr);
extern bool             IsFarFunc(sym_handle);
extern  unsigned        SavePendingLine(unsigned);
extern bool             AskIfUniqueLabel(label_handle);
extern bool             UseImportForm(fe_attr);
extern bool             AskIfCommonLabel(label_handle);
extern void             OutSpecialCommon(int,fix_class,bool);

extern void             DoLblRef( label_handle lbl, seg_id seg,
                                  offset val, byte kind );
static void             DoRelocRef( sym_handle sym, cg_class class,
                                    seg_id seg, offset val, byte kind );
static  void            OutShortDisp( label_handle lbl );
static  void            OutCodeDisp( label_handle lbl, fix_class f,
                                     bool rel, oc_class class );

extern byte             *NopLists[];

/* Grammar of Escapes :*/
/**/
/* Sequence                                             Meaning*/
/* ========                                             ========*/
/**/
/* ESC, ESC                                             actual ESC byte */
/* ESC, IMP <LDOF|OFST|BASE|SELF>, sym_handle <,offset> import reference */
/* ESC, REL <LDOF|BASE|OFST>, segid                     relocate, with seg-id*/
/* ESC, SYM <LDOF|OFST|SELF>, sym_handle <,offset>      unknown sym ref*/
/* ESC, LBL <LDOF|OFST|SELF>, segid, lbl_handle, <,offset> ptr reference*/
/* ESC, ABS objhandle, len, offset                      object patch*/
/* ESC, FUN byte                                        for 87 instructions*/
/**/
/*       OFST bit on means offset follows*/
/*       LDOF means loader resolved offset*/
/*       BASE means use F_BASE relocation*/

extern  bool    CodeHasAbsPatch( oc_entry *code ) {
/*************************************************/
    byte        *curr;
    byte        *final;

    curr = &code->data[ 0 ];
    final = curr + code->reclen - sizeof( oc_header );
    while( curr < final ) {
        if( *curr++ == ESC ) {
            if( *curr++ == ABS ) return( TRUE );
        }
    }
    return( FALSE );
}


extern  void    DoAbsPatch( abspatch_handle *handle, int len ) {
/**************************************************************/

    EmitByte( ESC );
    EmitByte( ABS );
    if( len == 1 ) {
        EmitByte( BYTE_PATCH );
    } else if( len == 2 ) {
        EmitByte( WORD_PATCH );
    } else { /*4*/
        EmitByte( LONG_PATCH );
    }
    *handle = NewAbsPatch();
    EmitPtr( *handle );
}


extern  void    DoFunnyRef( int segover ) {
/*****************************************/

/* yea, i know it's backwards*/
    InsertByte( segover );
    InsertByte( FUN );
    InsertByte( ESC );
}


extern  void  DoFESymRef( sym_handle sym, cg_class class, offset val,
                                int fixup ) {
/*******************************************************************/

    fe_attr             attr;
    byte                kind;

    kind = 0;
    switch( fixup ) {
    case FE_FIX_BASE:
        val = 0;
        kind |= BASE; /* base segment relocation */
        break;
    case FE_FIX_SELF:
        kind |= SELF; /* self relative offset relocation */
        break;
    }
    if( val != 0 ) {
        kind |= OFST;           /* offset follows*/
    }
    if( class == CG_FE ) {
        attr = FEAttr( sym );
        if( ((kind & BASE) == 0) && _IsTargetModel( WINDOWS )
         && ( attr & FE_PROC ) && IsFarFunc( sym ) ) {
            kind |= LDOF;
        }
        if( UseImportForm( attr ) ) { /* 90-05-22 */
            EmitByte( ESC );
            EmitByte( IMP | kind );
            EmitPtr( sym );
            if( kind & OFST ) {
                EmitOffset( val );
            }
        } else if( attr & FE_GLOBAL ) {
            DoRelocRef( sym, CG_FE, AskSegID( sym, CG_FE ), val, kind );
        } else {
            DoRelocRef( AskForSymLabel( sym, CG_FE ), CG_LBL,
                        AskSegID( sym, CG_FE ), val, kind );
        }
    } else {                                /* CG_TBL, CG_LBL or CG_BCK*/
        DoRelocRef( sym, class, AskSegID( sym, class ), val, kind );
    }
}


extern  void    DoSymRef( name *opnd, offset val, bool base ) {
/*************************************************************/

    DoFESymRef( opnd->v.symbol, opnd->m.memory_type, val,
                base ? FE_FIX_BASE : FE_FIX_OFF );
}


extern  void    DoSegRef( seg_id seg ) {
/**************************************/

    EmitByte( ESC );
    EmitByte( REL | BASE | OFST );
    EmitSegId( seg );
    EmitOffset( 0 );
}

static  void    DoRelocRef( sym_handle sym, cg_class class,
                            seg_id seg, offset val, byte kind ) {
/***************************************************************/

    offset              addr;
    label_handle        lbl;

    if( kind & BASE ) {                       /* don't need offset*/
        EmitByte( ESC );
        EmitByte( REL | kind | OFST );
        EmitSegId( seg );
        EmitOffset( 0 );
    } else {
        lbl = AskForSymLabel( sym, class );
        addr = AskAddress( lbl );
        if( (addr != ADDR_UNKNOWN) && !AskIfCommonLabel( lbl ) ) {
            EmitByte( ESC );
            EmitByte( REL | kind | OFST );
            EmitSegId( seg );
            val += addr;
            EmitOffset( val );
        } else if( class == CG_FE ) {
            EmitByte( ESC );
            EmitByte( SYM | kind );         /* patch may be needed*/
            EmitPtr( sym );
            if( kind & OFST ) {
                EmitOffset( val );
            }
        } else {
            DoLblRef( lbl, seg, val, kind );
        }
    }
}

extern  void    DoLblRef( label_handle lbl, seg_id seg,
                          offset val, byte kind ) {
/*************************************************/

    EmitByte( ESC );
    EmitByte( LBL | kind );
    EmitSegId( seg );
    EmitPtr( lbl );
    if( kind & OFST ) {
        EmitOffset( val );
    }
}

static void SendBytes( byte *ptr, unsigned len ) {
/************************************************/

    if( len != 0 ) OutDBytes( len, ptr );
}

#define INFO_NOT_DEBUG      INFO_SELECT
static oc_class SaveDbgOc = INFO_NOT_DEBUG;
static pointer  SaveDbgPtr;
static offset   LastUnique = ADDR_UNKNOWN;

static  void    DumpSavedDebug( void )
/******************************/
{
    switch( SaveDbgOc ) {
    case INFO_DBG_RTN_BEG:
        DbgRtnBeg( SaveDbgPtr, AskLocation() );
        break;
    case INFO_DBG_BLK_BEG:
        DbgBlkBeg( SaveDbgPtr, AskLocation() );
        break;
    case INFO_DBG_EPI_BEG:
        DbgEpiBeg( SaveDbgPtr, AskLocation() );
        break;
    }
    SaveDbgOc = INFO_NOT_DEBUG;
}

static void DoAlignment( int len ) {
/**********************************/

    byte                *ptr;
    int                 nop;
    int                 i;
    unsigned            save_line;

    save_line = SavePendingLine( 0 );
    /* get the size of the largest NOP pattern  */
    i = 0;
    for( nop = NopLists[i][0]; len > nop; len -= nop ) {
        SendBytes( &NopLists[i][1], nop );
        i = !i;
    }
    /* find the correct size NOP pattern to use */
    for( ptr = &NopLists[i][1]; nop != len; --nop ) ptr += nop;
    SendBytes( ptr, len );
    SavePendingLine( save_line );
}


static  void    ExpandCJ( any_oc *oc ) {
/**************************************/

    label_handle        lbl;
    oc_class            class;
    fix_class           f;
    bool                rel;

    lbl = oc->oc_handle.handle;
    class = oc->oc_entry.class;
    if( (class & GET_BASE) == OC_JCOND ) {
        if( oc->oc_entry.objlen == OptInsSize( OC_JCOND, OC_DEST_NEAR ) ) {
            if( _CPULevel( CPU_386 ) ) {
                _OutJCondNear( oc->oc_jcond.cond );
            } else {
                _OutJCond( ReverseCondition( oc->oc_jcond.cond ) );
                OutDataByte( OptInsSize( OC_JMP, OC_DEST_NEAR ) );
                _OutJNear;
            }
            OutCodeDisp( lbl, F_OFFSET, TRUE, class );
        } else {
            _OutJCond( oc->oc_jcond.cond );
            OutShortDisp( lbl );
        }
    } else if( (class & GET_BASE) == OC_JMP
         && oc->oc_entry.objlen == OptInsSize( OC_JMP, OC_DEST_SHORT ) ) {
        _OutJShort;
        OutShortDisp( lbl );
    } else {
        if( class & ATTR_FAR ) {
            f = F_PTR;
            rel = FALSE;
            if( ( class & GET_BASE ) == OC_CALL ) {
                if( oc->oc_entry.objlen == OptInsSize(OC_CALL, OC_DEST_CHEAP) ){
                    f = F_OFFSET;
                    rel = TRUE;
                    class &= ~ ATTR_FAR;
                    _OutCCyp;
                } else {
                    _OutCFar;
                }
            } else {
                _OutJFar;

⌨️ 快捷键说明

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