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 + -
显示快捷键?