extern void DupSeg( instruction *ins, instruction *new_ins ) { /****************************************************************/ if( ins->head.opcode == OP_BLOCK ) return; if( ins->num_operands <= NumOperands( ins ) ) return; if( new_ins->num_operands > NumOperands( new_ins ) ) return; new_ins->operands[ new_ins->num_operands++ ] = ins->operands[ ins->num_operands-1 ]; new_ins->t.index_needs = ins->t.index_needs; }
extern void DelSeg( instruction *ins ) { /******************************************/ if( NumOperands( ins ) < ins->num_operands ) { ins->num_operands--; } }
extern instruction *NeedIndex( instruction *ins ) { /******************************************************* Mark conflicts for any name used in instruction as as segment as NEEDS_SEGMENT, or split out the segment if it is marked as NEEDS_SEGMENT_SPLIT (move the segment operand to a temp and use the temp as the segment override). Also, if any index conflicts are marked as NEEDS_INDEX_SPLIT, split them out into a temp as well. */ name *temp; name *index; conflict_node *conf; name *name; if( ins->num_operands > NumOperands( ins ) ) { name = ins->operands[ins->num_operands - 1]; conf = NameConflict( ins, name ); if( conf != NULL && _Isnt( conf, CST_NEEDS_SEGMENT_SPLIT ) ) { _SetTrue( conf, CST_NEEDS_SEGMENT ); MarkSegment( ins, name ); } else if( name->n.class != N_REGISTER ) { if( conf != NULL ) { _SetFalse( conf, CST_NEEDS_SEGMENT ); _SetTrue( conf, CST_WAS_SEGMENT ); } temp = AllocTemp( U2 ); ins->operands[ins->num_operands - 1] = temp; PrefixIns( ins, MakeMove( name, temp, U2 ) ); MarkSegment( ins, temp ); _SetTrue( NameConflict( ins, temp ), CST_SEGMENT_SPLIT ); ins = ins->head.prev; } }
static fp_attr FPAttr( instruction *ins ) { /*******************************************/ if( _OpIsCall( ins->head.opcode ) && ins->result != NULL ) { if( ins->result->n.class != N_REGISTER ) return( POPS_ALL ); if( !HW_COvlap( ins->result->r.reg, HW_FLTS ) ) return( POPS_ALL ); return( PUSHES+POPS_ALL ); } if( ins->u.gen_table->generate == G_FCHOP ) return( NEEDS_ST0 ); if( !_GenIs8087( ins->u.gen_table->generate ) ) { return( NEEDS_NOTHING ); } switch( ins->u.gen_table->generate ) { case G_RRFBINP: case G_RNFBINP: return( NEEDS_ST0+POPS+SETS_ST1 ); case G_MFLD: case G_FLDZ: case G_FLD1: case G_RFLD: return( PUSHES ); case G_FRNDINT: case G_FCHS: case G_MFSTNP: case G_RFSTNP: case G_FTST: case G_FMATH: case G_RRFBIN: case G_RNFBIN: case G_MRFBIN: case G_MNFBIN: return( NEEDS_ST0 ); case G_FCOMPP: return( NEEDS_ST0_ST1+POPS2 ); case G_MFST: case G_MFSTRND: case G_RFST: case G_MCOMP: case G_RCOMP: return( NEEDS_ST0+POPS ); case G_IFUNC: if( NumOperands( ins ) == 2 ) { return( NEEDS_ST0_ST1+POPS ); } else { return( NEEDS_ST0 ); } case G_FXCH: return( NEEDS_ST0+EXCHANGES ); case G_FSINCOS: default: Zoiks( ZOIKS_075 ); return( NEEDS_NOTHING ); } }
extern void DelSegRes( instruction *ins ) { /*********************************************/ int i; if( ins->num_operands <= NumOperands( ins ) ) return; if( !SegMemLoc( ins->result ) ) return; i = ins->num_operands; while( --i >= 0 ) { if( ins->result == ins->operands[ i ] ) return; } DelSeg( ins ); }
extern void DelSegOp( instruction *ins, int i ) { /***************************************************/ int j; if( ins->num_operands <= NumOperands( ins ) ) return; if( !SegMemLoc( ins->operands[ i ] ) ) return; if( ins->result == ins->operands[ i ] ) return; j = ins->num_operands; while( --j >= 0 ) { if( i != j ) { if( ins->operands[ j ] == ins->operands[ i ] ) return; } } DelSeg( ins ); }
static void MoveSeg( instruction *ins, instruction *new_ins, name *op, bool save_old ) { /**************************************************/ int i; if( ins->head.opcode == OP_BLOCK ) return; if( ins->num_operands <= NumOperands( ins ) ) return; if( !SegMemLoc( op ) ) return; DupSeg( ins, new_ins ); if( save_old ) return; i = ins->num_operands; while( --i >= 0 ) { if( op == ins->operands[ i ] ) return; } if( op == ins->result ) return; DelSeg( ins ); }