i86split.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,100 行 · 第 1/3 页
C
1,100 行
/**********************************************/
constant_defn *defn;
unsigned_32 *low;
unsigned_32 *high;
defn = GetFloat( name, FD );
low = (unsigned_32 *)&defn->value[ 0 ];
high = (unsigned_32 *)&defn->value[ 2 ];
return( AllocU64Const( *low, *high ) );
}
extern instruction *rFSCONSCMP( instruction *ins ) {
/******************************************************/
name *name1;
name1 = ins->operands[ 1 ];
if( CFTest( name1->c.value ) > 0 ) {
ChangeType( ins, I4 );
} else {
ChangeType( ins, U4 );
RevCond( ins );
}
ins->operands[ 1 ] = IntEquivalent( name1 );
ins->table = NULL;
return( ins );
}
extern instruction *rHIGHLOWMOVE( instruction *ins ) {
/********************************************************/
instruction *new_ins;
/* for moving constants such as 0xabcdabcd*/
new_ins = MakeMove( LowPart( ins->result, U2 ),
HighPart( ins->result, U2 ),
U2 );
ins->result = LowPart( ins->result, U2 );
ChangeType( ins, U2 );
DupSegRes( ins, new_ins );
SuffixIns( ins, new_ins );
return( ins );
}
#if _TARGET & _TARG_80386
#define CX HW_ECX
#define DI HW_EDI
#define ES_DI HW_ES_EDI
#define SI HW_ESI
#define DS_SI HW_DS_ESI
#define LP CP
#define MOV_SIZE 5
#else
#define CX HW_CX
#define DI HW_DI
#define ES_DI HW_ES_DI
#define SI HW_SI
#define DS_SI HW_DS_SI
#define LP PT
#define MOV_SIZE 3
#endif
#define hw( x ) x
bool UseRepForm( unsigned size )
/*************************************
Do we want to use "rep movs{w|d}", or string out multiple "movs{w|d}"
*/
{
unsigned count;
unsigned extra = 0;
unsigned rep_startup;
unsigned rep_iter;
unsigned movs_cost;
count = size / WORD_SIZE;
/* if move than 10 movs, then always use rep form */
if( count > 10 ) return( TRUE );
if( OptForSize > 50 ) {
switch( size % WORD_SIZE ) {
case 0: extra = 0; break;
case 1: extra = 1; break;
case 2: extra = 1; break;
case 3: extra = 2; break;
}
return( count + extra > MOV_SIZE + 2 );
}
if( _CPULevel( CPU_586 ) ) {
rep_startup = 11;
rep_iter = 1;
movs_cost = 4;
} else if( _CPULevel( CPU_486 ) ) {
rep_startup = 12;
rep_iter = 3;
movs_cost = 7;
} else if( _CPULevel( CPU_386 ) ) {
rep_startup = 8;
rep_iter = 4;
movs_cost = 8;
} else if( _CPULevel( CPU_286 ) ) {
rep_startup = 5;
rep_iter = 4;
movs_cost = 5;
} else {
rep_startup = 9;
rep_iter = 17;
movs_cost = 18;
}
/* The "+ 4" is to account for the "MOV [E]CX, const" clocks and some
slop for larger instructions (cache effects) */
return( rep_startup + (count * rep_iter) + 4 < movs_cost * count );
}
static bool CanLoadStringOps( instruction *ins ) {
/****************************************************/
hw_reg_set needs;
if( UseRepForm( ins->operands[ 0 ]->n.size ) ) {
needs = CX;
} else {
HW_CAsgn( needs, HW_EMPTY );
}
HW_CAsgn( needs, hw( SI ) );
HW_CTurnOn( needs, hw( DI ) );
if( _IsTargetModel( FLOATING_DS ) ) {
HW_CTurnOn( needs, HW_DS );
}
if( _IsTargetModel( FLOATING_ES ) ) {
HW_CTurnOn( needs, HW_ES );
}
return( !HW_Ovlap( needs, ins->head.live.regs ) );
}
static name *FakeIndex( name *op, hw_reg_set index ) {
/****************************************************/
name *base;
i_flags flags;
if( op->n.class==N_TEMP || op->n.class==N_MEMORY ) {
base = op;
flags = X_FAKE_BASE;
} else {
base = NULL;
flags = EMPTY;
}
return( ScaleIndex( AllocRegName( index ), base, 0,
op->n.name_class, op->n.size, 0, flags ) );
}
static bool SegmentFloats( name *op ) {
/***************************************/
name *segname;
segname = SegName( op );
if( segname->n.class != N_REGISTER ) return( TRUE );
if( HW_COvlap( segname->r.reg, HW_DS ) ) return( _IsTargetModel( FLOATING_DS ) );
if( HW_COvlap( segname->r.reg, HW_SS ) ) return( _IsTargetModel( FLOATING_SS ) );
return( TRUE );
}
static instruction *LoadStringOps( instruction *ins,
name **op1, name **op2 ) {
/****************************************************************/
instruction *load_op1;
instruction *load_op2;
instruction *load_len;
instruction *first_ins;
instruction *pop;
name *ds_reg;
name *es_reg;
hw_reg_set new_op1;
bool ds_needs_save;
bool es_needs_save;
if( ins->head.opcode == OP_MOV && !UseRepForm( (*op1)->n.size ) ) {
load_len = NULL;
HW_CAsgn( new_op1, HW_EMPTY );
} else {
if( ( (*op1)->n.size & (WORD_SIZE-1) ) == 0
|| ( OptForSize <= 50 && ins->head.opcode == OP_MOV ) ) {
load_len = MoveConst((*op1)->n.size/WORD_SIZE,AllocRegName(CX),WD);
PrefixIns( ins, load_len );
} else {
load_len = MoveConst( (*op1)->n.size, AllocRegName(CX), WD );
PrefixIns( ins, load_len );
}
new_op1 = CX;
}
/* careful here. Make sure we load DS last*/
if( ins->num_operands > NumOperands( ins ) ) {
if( (*op1)->n.class == N_INDEXED || (*op1)->n.class == N_MEMORY ) {
load_op1 = MakeUnary( OP_LA, *op2, AllocRegName(ES_DI), LP );
PrefixIns( ins, load_op1 );
load_op2 = MakeUnary( OP_LA, *op1, AllocRegName( SI ), WD );
PrefixIns( ins, load_op2 );
load_op2 = MakeMove( ins->operands[ ins->num_operands-1 ],
AllocRegName( HW_DS ), U2 );
PrefixIns( ins, load_op2 );
es_needs_save = SegmentFloats( *op2 );
ds_needs_save = TRUE;
} else {
load_op1 = MakeMove( ins->operands[ ins->num_operands-1 ],
AllocRegName( HW_ES ), U2 );
PrefixIns( ins, load_op1 );
load_op2 = MakeUnary( OP_LA, *op2, AllocRegName( DI ), WD );
PrefixIns( ins, load_op2 );
load_op2 = MakeUnary( OP_LA, *op1, AllocRegName(DS_SI), LP );
PrefixIns( ins, load_op2 );
ds_needs_save = SegmentFloats( *op1 );
es_needs_save = TRUE;
}
DelSeg( ins );
} else if( _IsTargetModel( FLAT_MODEL ) &&
!SegmentFloats( *op1 ) && !SegmentFloats( *op2 ) ) {
load_op1 = MakeUnary( OP_LA, *op2, AllocRegName( DI ), WD );
PrefixIns( ins, load_op1 );
load_op2 = MakeUnary( OP_LA, *op1, AllocRegName( SI ), WD );
PrefixIns( ins, load_op2 );
ds_needs_save = es_needs_save = FALSE;
} else {
load_op1 = MakeUnary( OP_LA, *op2, AllocRegName( ES_DI ), LP );
PrefixIns( ins, load_op1 );
load_op2 = MakeUnary( OP_LA, *op1, AllocRegName( DS_SI ), LP );
PrefixIns( ins, load_op2 );
ds_needs_save = SegmentFloats( *op1 );
es_needs_save = SegmentFloats( *op2 );
}
if( _IsntTargetModel( FLOATING_DS ) && ds_needs_save ) { /* restore DS*/
ds_reg = AllocRegName( HW_DS );
pop = MakeUnary( OP_POP, NULL, ds_reg, U2 );
pop->num_operands = 0;
SuffixIns( ins, pop );
PrefixIns( load_op2, MakeUnary( OP_PUSH, ds_reg, NULL, U2 ) );
}
if( _IsntTargetModel( FLOATING_ES ) && es_needs_save ) { /* restore ES */
es_reg = AllocRegName( HW_ES );
pop = MakeUnary( OP_POP, NULL, es_reg, U2 );
pop->num_operands = 0;
SuffixIns( ins, pop );
PrefixIns( load_op1, MakeUnary( OP_PUSH, es_reg, NULL, U2 ) );
load_op1 = load_op1->head.prev;
}
HW_CTurnOn( new_op1, hw( DS_SI ) );
HW_CTurnOn( new_op1, hw( ES_DI ) );
ins->table = String;
ins->head.state = INS_NEEDS_WORK;
*op1 = FakeIndex( ins->operands[0], new_op1 );
ins->operands[ 1 ] = ins->operands[ 0 ];
HW_CTurnOff( new_op1, HW_SS );
HW_CTurnOff( new_op1, HW_SP );
HW_CTurnOff( new_op1, HW_ES );
HW_CTurnOff( new_op1, HW_DS );
ins->zap = &AllocRegName( new_op1 )->r;
if( ins->head.opcode == OP_MOV ) {
ins->result = FakeIndex( ins->result, ES_DI );
} else {
ins->result = NULL;
}
if( load_len != NULL ) {
first_ins = load_len;
} else {
first_ins = load_op1;
}
UpdateLive( first_ins, ins );
return( first_ins );
}
extern instruction *rMAKESTRCMP( instruction *ins ) {
/*******************************************************/
return( LoadStringOps( ins, &ins->operands[ 0 ], &ins->operands[ 1 ] ) );
}
extern instruction *rMAKESTRMOVE( instruction *ins ) {
/********************************************************/
return( LoadStringOps( ins, &ins->operands[ 0 ], &ins->result ) );
}
extern instruction *rMAYBSTRMOVE( instruction *ins ) {
/********************************************************/
if( CanLoadStringOps( ins ) ) {
return( LoadStringOps( ins, &ins->operands[ 0 ], &ins->result ) );
} else {
return( rSPLIT8( ins ) );
}
}
extern instruction *rEXT_PUSHC( instruction *ins ) {
/******************************************************/
CnvOpToInt( ins, 0 );
ChangeType( ins, WD );
return( ins );
}
extern instruction *rMOVELOW( instruction *ins ) {
/****************************************************/
/* e.g. convert U2==>U1*/
ins->head.opcode = OP_MOV;
ins->operands[ 0 ] = LowPart( ins->operands[ 0 ], ins->type_class );
ins->table = NULL;
return( ins );
}
extern instruction *rSPLITUNARY( instruction *ins ) {
/*******************************************************/
instruction *new_ins;
CnvOpToInt( ins, 0 );
new_ins = SplitUnary( ins );
return( new_ins );
}
extern instruction *rMOVRESMEM( instruction *ins ) {
/******************************************************/
instruction *new_ins;
name *name_flt;
name *name_int;
type_class_def class;
class = ins->type_class;
name_flt = AllocTemp( class );
if( class == FD || class == FL ) {
name_int = name_flt;
} else {
name_int = TempOffset( name_flt, 0, U4 );
}
name_flt->v.usage |= USE_MEMORY | NEEDS_MEMORY;
new_ins = MakeMove( name_int, ins->result, name_int->n.name_class);
ins->result = name_flt;
MoveSegRes( ins, new_ins );
SuffixIns( ins, new_ins );
return( ins );
}
extern instruction *rMOVOP1MEM( instruction *ins ) {
/******************************************************/
instruction *new_ins;
name *name_flt;
name *name_int;
type_class_def class;
class = ins->type_class;
name_flt = AllocTemp( class );
if( class == FD || class == FL ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?