i86enc32.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,002 行 · 第 1/3 页
C
1,002 行
OutRTImport( RT_Far32Func - BEG_RTNS, F_FAR16 );
OutDataInt( 0 );
OutDataInt( 0 );
if( remove_parms ) {
OutDataByte( 0xca );
OutDataInt( parms_size );
} else {
OutDataByte( 0xcb );
OutDataInt( 0 ); // padding
}
// emit "reloc for offset of code_32 label"
SetUpObj( TRUE );
TellKeepLabel( code_32 );
OutReloc( AskCodeSeg(), F_OFFSET, FALSE );
OutLblPatch( code_32, F_OFFSET, 0 );
TellByPassOver();
SetOP( old );
return( code_32 );
}
void GenProfilingCode( char *fe_name, label_handle *data, bool prolog )
/************************************************************************/
{
if( _IsTargetModel( NEW_P5_PROFILING ) ) {
doProfilingCode( fe_name, data, prolog );
}
}
segment_id GenP5ProfileData( char *fe_name, label_handle *data, label_handle *stack )
/***********************************************************************************/
{
seg_id old;
segment_id data_seg = (segment_id)FEAuxInfo( NULL, P5_PROF_SEG );
old = SetOP( data_seg );
TellOptimizerByPassed();
SetUpObj( TRUE );
*data = AskForNewLabel();
OutLabel( *data );
OutDataByte( *fe_name ); //flag
OutDataByte( 0 );
OutDataByte( 0 );
OutDataByte( 0 );
OutDataLong( 0 ); //semaphore
if( stack == NULL ) {
OutDataLong( 0 ); //stack
} else {
OutReloc( data_seg, F_OFFSET, FALSE ); //caller
OutLblPatch( *stack, F_OFFSET, 0 );
}
OutDataLong( 0 ); //esp
OutDataLong( 0 ); //dynamic
OutDataLong( 0 ); //lo_count
OutDataLong( 0 ); //hi_count
OutDataLong( 0 ); //lo_cycle
OutDataLong( 0 ); //hi_cycle
OutDataLong( 0 ); //lo_start_time
OutDataLong( 0 ); //hi_start_time
OutReloc( AskCodeSeg(), F_OFFSET, FALSE ); //caller
OutLblPatch( CurrProc->label, F_OFFSET, 0 );
OutDataLong( 0 ); //call_ins
OutDataLong( 0 ); //callee
TellByPassOver();
SetOP( old );
return( data_seg );
}
void doProfilingCode( char *fe_name, label_handle *data, bool prolog )
/***********************************************************************/
{
if( prolog ) GenP5ProfileData( fe_name, data, NULL );
_Code;
LayOpbyte( 0x68 );
ILen += 4;
DoLblRef( *data, (segment_id)FEAuxInfo( NULL, P5_PROF_SEG ), 0, FE_FIX_OFF | OFST);
_Emit;
RTCall( prolog ? RT_PROFILE_ON : RT_PROFILE_OFF, ATTR_POP );
}
static void doProfilingPrologEpilog( label_handle label, bool prolog )
/************************************************************************/
{
if( _IsTargetModel( NEW_P5_PROFILING ) ) {
doProfilingCode( "", &CurrProc->targ.routine_profile_data, prolog );
} else {
bck_info *bck;
label_handle data_lbl;
segment_id data_seg;
bck = (bck_info *)FEAuxInfo( AskForLblSym( label ), P5_PROF_DATA );
if( bck == NULL ) return;
data_lbl = bck->lbl;
data_seg = (segment_id)FEAuxInfo( NULL, P5_PROF_SEG );
TellKeepLabel( data_lbl );
_Code;
if( prolog ) {
LayOpword( 0x05ff );
ILen += 4;
DoLblRef( data_lbl, data_seg, offsetof( P5_timing_info, count ), FE_FIX_OFF | OFST);
_Next;
}
LayOpword( prolog ? 0x05ff : 0x0dff ); // inc L1 / dec L1
ILen += 4;
DoLblRef( data_lbl, data_seg, offsetof( P5_timing_info, semaphore ), FE_FIX_OFF | OFST );
_Next;
if( _IsTargetModel( P5_PROFILING_CTR0 ) ) {
LayOpword( prolog ? 0x1675 : 0x167d ); // jne skip / jge skip
_Next;
LayOpbyte( 0x51 ); // push ecx
_Next;
} else {
LayOpword( prolog ? 0x1275 : 0x127d ); // jne skip / jge skip
_Next;
}
LayOpbyte( 0x52 ); // push edx
_Next;
if( _IsTargetModel( P5_PROFILING_CTR0 ) ) {
LayOpword( 0xc931 ); // xor ecx,ecx
_Next;
}
LayOpbyte( 0x50 ); // push eax
_Next;
if( _IsTargetModel( P5_PROFILING_CTR0 ) ) {
LayOpword( 0x330f ); // rdpmc
_Next;
} else {
LayOpword( 0x310f ); // rdtsc
_Next;
}
LayOpword( prolog ? 0x0529 : 0x0501 ); // sub L1+4,eax / add L1+4,eax
ILen += 4;
DoLblRef( data_lbl, data_seg, offsetof( P5_timing_info, lo_cycle ), FE_FIX_OFF | OFST );
_Next;
LayOpbyte( 0x58 ); // pop eax
_Next;
LayOpword( prolog ? 0x1519 : 0x1511 ); // sbb L1+8,edx / adc L1+8,edx
ILen += 4;
DoLblRef( data_lbl, data_seg, offsetof( P5_timing_info, hi_cycle ), FE_FIX_OFF | OFST );
_Next;
LayOpbyte( 0x5a ); // pop edx
_Next;
if( _IsTargetModel( P5_PROFILING_CTR0 ) ) {
LayOpbyte( 0x59 ); // pop ecx
_Next;
}
_Emit;
}
}
extern void GenP5ProfilingProlog( label_handle label )
/********************************************************/
{
doProfilingPrologEpilog( label, TRUE );
}
extern void GenP5ProfilingEpilog( label_handle label )
/********************************************************/
{
doProfilingPrologEpilog( label, FALSE );
}
extern void GFstp10( type_length where )
/******************************************/
{
GCondFwait();
CheckSize();
LayOpword( 0x3ddb );
EA( HW_EMPTY, HW_BP, 0, -where, NULL, FALSE );
_Emit;
}
extern void GFld10( type_length where )
/*****************************************/
{
GCondFwait();
CheckSize();
LayOpword( 0x2ddb );
EA( HW_EMPTY, HW_BP, 0, -where, NULL, FALSE );
_Emit;
}
extern void Do4Shift( instruction *ins ) {
/********************************************/
/* NOT NEEDED */ ins = ins;
}
extern void Do4RShift( instruction *ins )
/*******************************************/
/* NOT NEEDED ON 386 */
{
ins = ins;
}
extern void Gen4RNeg( instruction *ins )
/******************************************/
/* NOT NEEDED ON 386 */
{
ins = ins;
}
extern void Pow2Div( instruction *ins )
/*****************************************/
{
int log2;
bool if_32;
if_32 = FALSE;
log2 = GetLog2( ins->operands[1]->c.int_value );
switch( ins->type_class ) {
case I1:
case U1:
LayOpword( 0xe4c0 ); /* shl ah,n */
AddByte( log2 );
_Next;
LayOpword( 0xc41a ); /* sbb al,ah */
_Next;
LayOpword( 0xf8c0 ); /* sar al,n */
AddByte( log2 );
break;
case I2:
case U2:
if_32 = TRUE;
case I4:
case U4:
LayOpword( 0xe2c1 ); /* shl edx,n */
OpndSizeIf( if_32 );
AddByte( log2 );
_Next;
LayOpword( 0xc21b ); /* sbb eax,edx */
OpndSizeIf( if_32 );
_Next;
LayOpword( 0xf8c1 ); /* sar eax,n */
OpndSizeIf( if_32 );
AddByte( log2 );
break;
}
}
extern void By2Div( instruction *ins )
/****************************************/
{
bool if_32;
if_32 = FALSE;
switch( ins->type_class ) {
case I1:
case U1:
LayOpword( 0xc42a ); /* sub al,ah */
_Next;
LayOpword( 0xf8d0 ); /* sar al,1 */
break;
case I2:
case U2:
if_32 = TRUE;
case I4:
case U4:
LayOpword( 0xc22b ); /* sub eax,edx */
OpndSizeIf( if_32 );
_Next;
LayOpword( 0xf8d1 ); /* sar eax,1 */
OpndSizeIf( if_32 );
break;
}
}
extern void Gen4Neg( instruction *ins )
/*****************************************/
/* NOT NEEDED ON 386 */
{
ins = ins;
}
extern void Do4CXShift( instruction *ins, void (*rtn)(instruction *) )
/************************************************************************/
/* NOT NEEDED ON 386 */
{
ins = ins; rtn = rtn;
}
void StartBlockProfiling( block *blk )
/************************************/
{
seg_id old;
segment_id data_seg;
label_handle data;
if( !_IsTargetModel( NEW_P5_PROFILING ) ) return;
if( !_IsTargetModel( STATEMENT_COUNTING ) ) return;
data_seg = (segment_id)FEAuxInfo( NULL, P5_PROF_SEG );
if( blk->label == NULL ) return;
TellKeepLabel( blk->label );
old = SetOP( data_seg );
TellOptimizerByPassed();
SetUpObj( TRUE );
data = AskForNewLabel();
TellKeepLabel( data );
OutLabel( data );
OutDataByte( PROFILE_FLAG_BLOCK ); //flag
OutDataByte( 0 ); //...
OutDataByte( 0 ); //...
OutDataByte( 0 ); //...
OutDataLong( 0 ); //lo_count
OutDataLong( 0 ); //hi_count
OutReloc( AskCodeSeg(), F_OFFSET, FALSE ); //block
OutLblPatch( blk->label, F_OFFSET, 0 );
OutReloc( AskCodeSeg(), F_OFFSET, FALSE ); //function
OutLblPatch( CurrProc->label, F_OFFSET, 0 );
TellByPassOver();
SetOP( old );
_Code;
LayOpword( 0x0583 ); // sub L1+4,eax / add L1+4,eax
ILen += 4;
DoLblRef( data, data_seg, offsetof( block_count_info, lo_count ), FE_FIX_OFF | OFST );
AddByte( 1 );
_Next;
LayOpword( 0x1583 ); // sub L1+4,eax / add L1+4,eax
ILen += 4;
DoLblRef( data, data_seg, offsetof( block_count_info, hi_count ), FE_FIX_OFF | OFST );
AddByte( 0 );
_Emit;
}
void EndBlockProfiling( void )
/****************************/
{
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?