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