Ejemplo n.º 1
0
static  name    *GetGenericTLSDataRef( instruction *ins, name *op, type_class_def tipe )
/**************************************************************************************/
{
    name                *tls;
    name                *result_index;
    name                *temp;
    instruction         *new_ins;


    tls = CurrProc->targ.tls_index;
    if( tls == NULL ) {
        tls = AllocTemp( WD );
        CurrProc->targ.tls_index = tls;
        if( !BlockByBlock ) {
            /* 2007-06-28 RomanT
             * Grrr... DropCall() inserts new ins _before_ old one, screwing
             * startup sequence. So keep call in first block, but make it
             * before next instruction of last one  (== after last one).
             */
            DropCall( HeadBlock->ins.hd.prev->head.next, tls );
        }
    }
    if( BlockByBlock ) {
        DropCall( ins, tls );
    }
    temp = AllocTemp( WD );
    new_ins = MakeMove( tls, temp, WD );
    PrefixIns( ins, new_ins );
    result_index = ScaleIndex( temp, op, op->v.offset, tipe, TypeClassSize[ tipe ], 0, 0 );
    return( result_index );
}
Ejemplo n.º 2
0
static  name    *GetNTTLSDataRef( instruction *ins, name *op, type_class_def tipe )
/**********************************************************************************
    Emit instructions to load allow a reference to op (a piece of
    TLS data) and return the resulting index name.
*/
{
    name                *tls_index;
    name                *tls_array;
    name                *t1;
    name                *t2;
    name                *t3;
    name                *temp_index;
    name                *result_index;
    instruction         *new_ins;

    tls_index = RTMemRef( RT_TLS_INDEX );
    tls_array = RTMemRef( RT_TLS_ARRAY );
    t1 = AllocTemp( WD );
    t2 = AllocTemp( WD );
    t3 = AllocTemp( WD );
    new_ins = MakeMove( tls_array, t1, WD );
    AddSegOverride( new_ins, HW_FS );
    PrefixIns( ins, new_ins );
    new_ins = MakeMove( tls_index, t2, WD );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_MUL, t2, AllocS32Const( 4 ), t2, WD );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_ADD, t1, t2, t1, WD );
    PrefixIns( ins, new_ins );
    temp_index = AllocIndex( t1, NULL, 0, WD );
    new_ins = MakeMove( temp_index, t3, WD );
    PrefixIns( ins, new_ins );
    result_index = ScaleIndex( t3, op, op->v.offset, tipe, TypeClassSize[ tipe ], 0, 0 );
    return( result_index );
}
Ejemplo n.º 3
0
name    *StReturn( an retval, type_def *tipe, instruction **pins )
/****************************************************************/
{
    name        *retp;
    name        *ptr;
    name        *off;
    name        *seg;
    hw_reg_set  reg;

    if( CurrProc->state.attr & ROUTINE_ALLOCS_RETURN ) {
        retp = CurrProc->targ.return_points;
        AddIns( MakeUnary( OP_LA, retp, AllocRegName( CurrProc->state.return_reg ), WD ) );
        *pins = NULL;
    } else {
        if( _IsTargetModel( FLOATING_SS ) || _IsTargetModel( FLOATING_DS ) ) {
            ptr = AllocTemp( CP );
            off = OffsetPart( ptr );
            seg = SegmentPart( ptr );
            AddIns( MakeMove( AllocRegName( HW_SS ), seg, U2 ) );
        } else {
            ptr = AllocTemp( WD );
            off = ptr;
        }
        AddIns( MakeMove( CurrProc->targ.return_points, off, WD ) );
        retp = SAllocIndex( ptr, NULL, 0, TypeClass( retval->tipe ), tipe->length );
        reg = ReturnReg( WD, false );
        *pins = MakeMove( CurrProc->targ.return_points, AllocRegName( reg ), WD );
        CurrProc->state.return_reg = reg;
    }
    return( retp );
}
Ejemplo n.º 4
0
static instruction      *PromoteOperand( instruction *ins ) {
/***********************************************************/

    name                *temp;
    instruction         *new_ins;

    if( _IsFloating( ins->type_class ) ) {
        if( ins->type_class == FS ) {
            temp = AllocTemp( FD );
            new_ins = MakeConvert( ins->operands[0], temp, ins->type_class, FD );
            ins->operands[0] = temp;
            PrefixIns( ins, new_ins );
            UpdateLive( new_ins, ins );
            return( new_ins );
        }
    } else {
        if( ins->type_class < U8 ) {
            temp = AllocTemp( U8 );
            new_ins = MakeConvert( ins->operands[0], temp, ins->type_class, U8 );
            ins->operands[0] = temp;
            PrefixIns( ins, new_ins );
            UpdateLive( new_ins, ins );
            return( new_ins );
        }
    }
    return( NULL );
}
Ejemplo n.º 5
0
static  void    CheckOp( name **offsets, instruction *ins, name **pop ) {
/************************************************************************
    used by FixFarLocalRefs to change one far local reference to
    an index, using the appropriate multiple of 4K constant to get
    at the temporary. The constant values are adjusted after the
    prolog is generated.
*/

    name        *op;
    name        *base;
    name        *temp;
    unsigned_32 place;
    int         i;
    instruction *new_ins;

    op = *pop;
    if( op->n.class == N_INDEXED ) {
        temp = op->i.index;
        if( temp->n.class != N_TEMP ) return;
        if( !( temp->t.temp_flags & FAR_LOCAL ) ) return;
        new_ins = MakeMove( temp, AllocTemp( temp->n.name_class ), temp->n.name_class );
        *pop = ScaleIndex( new_ins->result, op->i.base,
                          op->i.constant, op->n.class, op->n.size,
                          op->i.scale, op->i.index_flags );
        PrefixIns( ins, new_ins );
        CheckOp( offsets, new_ins, &new_ins->operands[ 0 ] );
    }
    if( op->n.class != N_TEMP ) return;
    if( !( op->t.temp_flags & FAR_LOCAL ) ) return;
    base = DeAlias( op );
    place = base->t.location + ( op->v.offset - base->v.offset );
    i = place/_4K;
    if( offsets[ i ] == NULL ) {
        /*set the symbol field in the AddrConst to non-NULL for score-boarder*/
        new_ins = MakeMove( AllocAddrConst( (name *)&CurrProc, i,
                                            CONS_OFFSET, WD ),
                        AllocTemp( WD ), WD );
        offsets[ i ] = new_ins->result;
        PrefixIns( HeadBlock->ins.hd.next, new_ins );
    }
    temp = AllocTemp( WD ),
    new_ins = MakeMove( offsets[ i ], temp, WD );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_ADD, temp, AllocRegName( DisplayReg() ), temp, WD);
    PrefixIns( ins, new_ins );
    *pop = ScaleIndex( temp, op, place%_4K,
                        op->n.name_class, op->n.size, 0, X_FAKE_BASE );
}
Ejemplo n.º 6
0
extern void BGProcDecl( cg_sym_handle sym, type_def *tipe )
/******************************************************/
{
    type_class_def      class;
    name                *temp;
    hw_reg_set          reg;

    class = AddCallBlock( sym, tipe );
    SaveTargetModel = TargetModel;
    if( tipe != TypeNone ) {
        if( class == XX ) {
            // Handle structure returns - we need to "eat up" the first
            // register used for argument passing here, so that it isn't
            // used for passing actual arguments. NB: Must also bump
            // parm.offset here so that arguments end up in the right
            // locations.
            reg = HW_D4;
            temp = AllocTemp( WD );
            temp->v.usage |= USE_IN_ANOTHER_BLOCK;
            AddIns( MakeMove( AllocRegName( reg ), temp, WD ) );
            HW_TurnOn( CurrProc->state.parm.used, reg );
// TODO: need to do anything here?
//            HW_CTurnOn( CurrProc->state.parm.used, HW_F16 );
            CurrProc->targ.return_points = temp;
            CurrProc->state.parm.offset += REG_SIZE;
        }
    }
}
Ejemplo n.º 7
0
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;
        }
    }
Ejemplo n.º 8
0
/* 370 */
instruction      *rUSEREGISTER( instruction *ins )
/************************************************/
{
    instruction         *new_ins;
    instruction         *ins2;
    name                *name1;

    name1 = ins->operands[0];
    if( CanUseOp1( ins, name1 ) ) {
        new_ins = MakeMove( name1, ins->result, ins->type_class );
        ins->result = name1;
        MoveSegRes( ins, new_ins );
        SuffixIns( ins, new_ins );
        new_ins = ins;
    } else {
        name1 = AllocTemp( ins->type_class );
        new_ins = MakeMove( ins->operands[0], name1, ins->type_class );
        CheckCC( ins, new_ins );
        ins->operands[0] = name1;
        MoveSegOp( ins, new_ins, 0 );
        PrefixIns( ins, new_ins );
        ins2 = MakeMove( name1, ins->result, ins->type_class );
        ins->result = name1;
        MoveSegRes( ins, ins2 );
        SuffixIns( ins, ins2 );
        MarkPossible( ins, name1, ResultPossible( ins ) );
        ins->u.gen_table = NULL;
        GiveRegister( NameConflict( ins, name1 ), true );
    }
    return( new_ins );
}
Ejemplo n.º 9
0
name        *BGNewTemp( type_def *tipe )
/**************************************/
{
    name        *temp;

    temp = AllocTemp( TypeClass( tipe ) );
    if( temp->n.size == 0 ) {
        temp->n.size = tipe->length;
    }
    return( temp );
}
Ejemplo n.º 10
0
extern  name    *MakeDisplay( name *op, int level )
/*************************************************/
{
    name        *temp;
    name        *reg;

    reg = AllocRegName( DisplayReg() );
    temp = AllocTemp( U2 );
    AddIns( MakeMove( DisplayField( level ), temp, reg->n.name_class ) );
    op = AllocIndex( temp, NULL, op->t.location, op->n.name_class );
    return( op );
}
Ejemplo n.º 11
0
instruction      *rMOVOP2TEMP( instruction *ins )
/***********************************************/
{
    instruction         *new_ins;
    name                *name1;

    name1 = AllocTemp( ins->type_class );
    new_ins = MakeMove( ins->operands[1], name1, ins->type_class );
    ins->operands[1] = name1;
    MoveSegOp( ins, new_ins, 0 );
    PrefixIns( ins, new_ins );
    return( new_ins );
}
Ejemplo n.º 12
0
instruction     *rMOVOP1TEMP( instruction *ins )
/**********************************************/
{
    instruction         *new_ins;
    type_class_def      type_class;
    name                *name;

    type_class = _OpClass( ins );
    name = AllocTemp( type_class );
    new_ins = MakeMove( ins->operands[0], name, type_class );
    ins->operands[0] = name;
    MoveSegOp( ins, new_ins, 0 );
    PrefixIns( ins, new_ins );
    return( new_ins );
}
Ejemplo n.º 13
0
instruction      *rMOVRESTEMP( instruction *ins )
/***********************************************/
{
    instruction         *new_ins;
    name                *name1;

    name1 = AllocTemp( ins->type_class );
    new_ins = MakeMove( name1, ins->result, ins->type_class );
    ins->result = name1;
    MoveSegRes( ins, new_ins );
    SuffixIns( ins, new_ins );
    MarkPossible( ins, name1, ResPossible( ins ) );
    ins->u.gen_table = NULL;
    return( ins );
}
Ejemplo n.º 14
0
/* 370 */
instruction      *rMOVRESREG( instruction *ins )
/**********************************************/
{
    instruction         *new_ins;
    name                *name1;

    name1 = AllocTemp( ins->type_class );
    new_ins = MakeMove( name1, ins->result, ins->type_class );
    ins->result = name1;
    MoveSegRes( ins, new_ins );
    SuffixIns( ins, new_ins );
    MarkPossible( ins, name1, ResPossible( ins ) );
    ins->u.gen_table = NULL;
    GiveRegister( NameConflict( ins, name1 ), true );
    return( ins );
}
Ejemplo n.º 15
0
extern  an      PassProcParm( an rtn ) {
/**************************************/

    name        *op;
    name        *reg;

    op = AllocTemp( XX );
    op->n.size = TypePtr->length + SizeDisplayReg();
    reg = AllocRegName( DisplayReg() );
    AddIns( MakeMove( GenIns( rtn ),
            TempOffset( op, 0, ClassPointer ),
            ClassPointer ) );
    AddIns( MakeMove( reg, TempOffset( op, TypePtr->length,
                                       reg->n.name_class ),
                      reg->n.name_class ) );
    return( AddrName( op, TypeProcParm ) );
}
Ejemplo n.º 16
0
instruction      *rOP2REG( instruction *ins )
/*******************************************/
{
    instruction         *new_ins;
    name                *name1;
    type_class_def      type_class;

    type_class = _OpClass( ins );
    name1 = AllocTemp( type_class );
    new_ins = MakeMove( ins->operands[1], name1, type_class );
    ins->operands[1] = name1;
    MoveSegOp( ins, new_ins, 0 );
    PrefixIns( ins, new_ins );
    MarkPossible( ins, name1, Op1Possible( ins ) );
    ins->u.gen_table = NULL;
    GiveRegister( NameConflict( ins, name1 ), true );
    return( new_ins );
}
Ejemplo n.º 17
0
extern  instruction     *rSPLITMOVE( instruction *ins ) {
/******************************************************/

    instruction *new_ins;
    instruction *ins2;
    name        *temp;

    CnvOpToInt( ins, 0 );
    if( IndexOverlaps( ins, 0 ) ) {
        temp = AllocTemp( LONG_WORD );
        new_ins = MakeMove( LowPart( ins->operands[ 0 ], WORD ),
                             LowPart( temp, WORD ), WORD );
        ins2 = MakeMove( HighPart( ins->operands[ 0 ], WORD ),
                             HighPart( temp, WORD ), WORD );
        DupSegOp( ins, new_ins, 0 );
        DupSegOp( ins, ins2, 0 );
        ins->operands[ 0 ] = temp;
        PrefixIns( ins, new_ins );
        PrefixIns( ins, ins2 );
        ins2 = MakeMove( LowPart( temp, WORD ), LowPart( ins->result, WORD ), WORD );
        DupSegRes( ins, ins2 );
        PrefixIns( ins, ins2 );
        ins2 = MakeMove( HighPart( temp, WORD ),
                          HighPart( ins->result, WORD ), WORD );
        ReplIns( ins, ins2 );
    } else {
        HalfType( ins );
        new_ins = MakeMove( LowPart( ins->operands[ 0 ], ins->type_class ),
                             LowPart( ins->result, ins->type_class ),
                             ins->type_class );
        DupSeg( ins, new_ins );
        ins->operands[ 0 ] = HighPart( ins->operands[ 0 ], ins->type_class );
        ins->result = HighPart( ins->result, ins->type_class );
        if( new_ins->result->n.class == N_REGISTER
         && ins->operands[ 0 ]->n.class == N_REGISTER
         && HW_Ovlap( new_ins->result->r.reg, ins->operands[ 0 ]->r.reg ) ) {
            SuffixIns( ins, new_ins );
            new_ins = ins;
        } else {
            PrefixIns( ins, new_ins );
        }
    }
Ejemplo n.º 18
0
static  void    AddCall( instruction *ins, cn call ) {
/****************************************************/

    name        *proc_name;

    if( _IsTargetModel(FLOATING_DS) && (call->state->attr&ROUTINE_NEEDS_DS_LOADED) ) {
        AddIns( MakeMove( NearSegment(), AllocRegName( HW_DS ), U2 ) );
    }
    if( call->name->tipe == TypeProcParm ) {
        proc_name = AllocTemp( ClassPointer );
/* what to do?        proc_name->usage |= USE_REGISTER;*/
        AddIns( MakeMove( ins->operands[CALL_OP_ADDR], proc_name, ClassPointer ));
        ins->operands[CALL_OP_ADDR] = proc_name;
        SetDisplay( GenIns( call->name ) );
        AddIns( ins );
        SaveDisplay( OP_POP );
    } else {
        AddCallIns( ins, call );
    }
}
Ejemplo n.º 19
0
void    BGProcDecl( cg_sym_handle sym, type_def *tipe )
/*****************************************************/
{
    type_class_def      class;
    name                *temp;
    hw_reg_set          reg;

    class = AddCallBlock( sym, tipe );
    SaveTargetModel = TargetModel;
    if( tipe != TypeNone ) {
        if( class == XX ) {
            reg = HW_D3;
            temp = AllocTemp( WD );
            temp->v.usage |= USE_IN_ANOTHER_BLOCK;
            AddIns( MakeMove( AllocRegName( reg ), temp, WD ) );
            HW_TurnOn( CurrProc->state.parm.used, reg );
            CurrProc->targ.return_points = temp;
        }
    }
}
Ejemplo n.º 20
0
instruction      *rCLRHI_BW( instruction *ins )
/*********************************************/
{
    instruction         *new_ins;
    instruction         *ins2;
    name                *name1;
    type_class_def      half_type_class;

    half_type_class = HalfClass[ins->type_class];
    name1 = AllocTemp( ins->type_class );
    new_ins = MakeMove( ins->operands[0], LowPart( name1, half_type_class ), half_type_class );
    ins->operands[0] = name1;
    MoveSegOp( ins, new_ins, 0 );
    PrefixIns( ins, new_ins );
    ins2 = MoveConst( 0, HighPart( name1, half_type_class ), half_type_class );
    PrefixIns( ins, ins2 );
    ins->head.opcode = OP_MOV;
    ins->table = NULL;
    ins->u.gen_table = NULL;
    return( new_ins );
}
Ejemplo n.º 21
0
void    BGProcDecl( cg_sym_handle sym, type_def *tipe )
/*****************************************************/
{
    hw_reg_set          reg;
    name                *temp;
    type_class_def      type_class;
    segment_id          old_segid;
    label_handle        lbl;

    SaveTargetModel = TargetModel;
    type_class = AddCallBlock( sym, tipe );
    if( tipe != TypeNone ) {
        if( type_class == XX ) {
            if( CurrProc->state.attr & ROUTINE_ALLOCS_RETURN ) {
                old_segid = SetOP( AskBackSeg() );
                lbl = AskForNewLabel();
                DataLabel( lbl );
                DGUBytes( tipe->length );
                CurrProc->targ.return_points = (name *)SAllocMemory( lbl, 0, CG_LBL, TypeClass( tipe ), tipe->length );
                SetOP( old_segid );
            } else {
                reg = CurrProc->state.return_reg;
                if( HW_CEqual( reg, HW_EMPTY ) ) {
                    temp = DoParmDecl( NULL, TypeInteger, HW_EMPTY );
                } else {
                    temp = AllocTemp( WD );
                    temp->v.usage |= USE_IN_ANOTHER_BLOCK;
                    AddIns( MakeMove( AllocRegName( reg ), temp, WD ) );
                    HW_TurnOn( CurrProc->state.parm.used, reg );
                }
                CurrProc->targ.return_points = temp;
            }
        }
    }
    if( CurrProc->state.attr & ROUTINE_FARSS ) {
        TargetModel |= FLOATING_SS;
    }
}
Ejemplo n.º 22
0
static  void    ExpandTlsOp( instruction *ins, name **pop )
/**********************************************************
    If *pop is a ref to a piece of thread-local data, replace
    it by a ref to an index [t1] and prepend the magic sequence
    to get the address of a piece of tls data to the instruction.
    Here is the sequence to access variable foo:
        mov fs:__tls_array -> t1
        mov __tls_index -> t2
        mov t2 * 4 -> t2
        add t1, t2 -> t1
        mov [ t1 ] -> t3
        mov foo[ t3 ] -> result
*/
{
    fe_attr             attr;
    name                *op;
    name                *temp;
    name                *tls_data;
    name                *index;
    name                *base;
    instruction         *new_ins;

    op = *pop;
    switch( op->n.class ) {
    case N_MEMORY:
        if( op->m.memory_type == CG_FE ) {
            attr = FEAttr( op->v.symbol );
            if( ( attr & FE_THREAD_DATA ) != 0 ) {
                *pop = GetTLSDataRef( ins, op, _OpClass(ins) );
            }
        }
        break;
    case N_INDEXED:
        // gotta check for the base being one of these stupid TLS things
        if( op->i.base != NULL && ( op->i.index_flags & X_FAKE_BASE ) == 0 ) {
            base = op->i.base;
            if( base->n.class != N_MEMORY || base->m.memory_type != CG_FE ) break;
            attr = FEAttr( base->v.symbol );
            if( ( attr & FE_THREAD_DATA ) == 0 ) break;
            tls_data = GetTLSDataRef( ins, base, _OpClass(ins) );
            temp = AllocTemp( WD );
            new_ins = MakeUnary( OP_LA, tls_data, temp, WD );
            PrefixIns( ins, new_ins );
            index = op->i.index;
            if( op->i.scale != 0 ) {
                const signed_32 values[] = { 1, 2, 4, 8, 16 };
                if( op->i.scale > 4 ) _Zoiks( ZOIKS_134 );
                index = AllocTemp( WD );
                new_ins = MakeBinary( OP_MUL, op->i.index,
                                AllocS32Const( values[ op->i.scale ] ),
                                index, WD );
                PrefixIns( ins, new_ins );
            }
            new_ins = MakeBinary( OP_ADD, temp, index, temp, WD );
            PrefixIns( ins, new_ins );
            *pop = ScaleIndex( temp, NULL, 0,
                            _OpClass(ins),
                            TypeClassSize[ _OpClass(ins) ],
                            0, 0 );
        }
        break;
    }
Ejemplo n.º 23
0
    4,
    1,
    2,
    1,
};

static  name    *MakeIndex( instruction *memory_ins, name *memory, type_class_def class ) {
/*****************************************************************************************/

    name        *op;
    name        *temp;
    instruction *ins;
    i_flags     flags;
    fe_attr     attr;

    temp = AllocTemp( WD );
    ins = MakeUnary( OP_LA, memory, temp, WD );
    PrefixIns( memory_ins, ins );
    // Note: this assumes we put Memory names on 8-byte boundaries
    flags = AlignmentToFlags( AlignmentMap[ memory->v.offset & 0x7 ] );
    if( memory->m.alignment != 0 ) {
        flags = AlignmentToFlags( memory->m.alignment );
    }
    if( memory->m.memory_type == CG_FE ) {
        attr = FEAttr( memory->v.symbol );
        if( attr & FE_VOLATILE ) {
            flags |= X_VOLATILE;
        }
        if( attr & FE_THREAD_DATA ) {
            // this is for the kooky expansion in axpenc.c - we have
            // to call rdteb, which destroys R0
Ejemplo n.º 24
0
/* Take advantage of the SETcc instruction in cases such as
 * x = y ? 3 : 4;
 * by adding a constant to the result of SETcc to directly obtain
 * the result of the assignment.
 */
static  bool    FindFlowOut( block *blk ) {
/*****************************************/

    signed_64           false_cons;
    signed_64           true_cons;
    signed_64           one;
    signed_64           neg_one;
    signed_64           diff;
    instruction         *ins;
    instruction         *ins0;
    instruction         *ins1;
//    instruction         *prev;
    block               *true_blk;
    block               *false_blk;
    block               *join_blk;
    block_edge          *new_edge;
    bool                reverse;
    name                *u1temp;
    name                *temp;
    name                *result;
    name                *konst;
    type_class_def      class;

    for( ins = blk->ins.hd.prev; !_OpIsCondition( ins->head.opcode ); ) {
        ins = ins->head.prev;
    }
//    prev = ins->head.prev;
    if( TypeClassSize[ ins->type_class ] > WORD_SIZE ) return( FALSE );
    true_blk = blk->edge[ _TrueIndex( ins ) ].destination.u.blk;
    if( true_blk->inputs != 1 ) return( FALSE );
    if( true_blk->targets != 1 ) return( FALSE );

    false_blk = blk->edge[ _FalseIndex( ins ) ].destination.u.blk;
    if( false_blk->inputs != 1 ) return( FALSE );
    if( false_blk->targets != 1 ) return( FALSE );

    join_blk = false_blk->edge[ 0 ].destination.u.blk;
    if( join_blk != true_blk->edge[ 0 ].destination.u.blk ) return( FALSE );
    if( join_blk->inputs != 2 ) return( FALSE );
    if( join_blk->class & UNKNOWN_DESTINATION ) return( FALSE );

    ins0 = SetToConst( false_blk, &false_cons );
    if( ins0 == NULL ) return( FALSE );
    ins1 = SetToConst( true_blk, &true_cons );
    if( ins1 == NULL ) return( FALSE );

    I32ToI64( 1, &one );
    I32ToI64( -1, &neg_one );
    U64Sub( &true_cons, &false_cons, &diff );
    if( U64Cmp( &diff, &neg_one ) == 0 ) {
        U64IncDec( &false_cons, -1 );
        reverse = TRUE;
    } else {
        if( U64Cmp( &diff, &one ) != 0 ) return( FALSE );
        reverse = FALSE;
    }
    result = ins0->result;
    if( result != ins1->result ) return( FALSE );
    class = ins0->type_class;
    if( class != ins1->type_class ) return( FALSE );

    if( reverse ) FlipCond( ins );

    u1temp = AllocTemp( U1 );
    temp = AllocTemp( class );

    ins->result = u1temp;
    ins1 = MakeConvert( u1temp, temp, class, U1 );
    SuffixIns( ins, ins1 );
    ins = ins1;

    if( I64Test( &false_cons ) != 0 ) {
        konst = AllocS64Const( false_cons.u._32[I64LO32], false_cons.u._32[I64HI32] );
        ins1 = MakeBinary( OP_ADD, temp, konst, result, class );
    } else {
Ejemplo n.º 25
0
extern  instruction     *rSPLITOP( instruction *ins ) {
/****************************************************/

    instruction *new_ins;
    instruction *ins2;
    name        *temp;

    if( IndexOverlaps( ins, 0 ) || IndexOverlaps( ins, 1 ) ) {
        temp = AllocTemp( LONG_WORD );
        HalfType( ins );
        new_ins = MakeBinary( ins->head.opcode,
                        LowPart( ins->operands[ 0 ], WORD ),
                        LowPart( ins->operands[ 1 ], WORD ),
                        LowPart( temp,               WORD ),
                        WORD );
        ins2 = MakeBinary( ins->head.opcode,
                        HighPart( ins->operands[ 0 ], WORD ),
                        HighPart( ins->operands[ 1 ], WORD ),
                        HighPart( temp,               WORD ),
                        WORD );
        if( ins->head.opcode == OP_ADD ) {
            ins2->head.opcode = OP_EXT_ADD;
        } else if( ins->head.opcode == OP_SUB ) {
            ins2->head.opcode = OP_EXT_SUB;
        }
        ins2->table = CodeTable( ins2 );
        new_ins->table = ins2->table;
        DupSegOp( ins, new_ins, 0 );
        DupSegOp( ins, ins2, 0 );
        DupSegOp( ins, new_ins, 1 );
        DupSegOp( ins, ins2, 1 );
        ins->operands[ 0 ] = temp;
        ins->operands[ 1 ] = temp;
        PrefixIns( ins, new_ins );
        PrefixIns( ins, ins2 );
        ins2 = MakeMove( LowPart( temp, WORD ), LowPart( ins->result, WORD ), WORD );
        DupSegRes( ins, ins2 );
        PrefixIns( ins, ins2 );
        ins2 = MakeMove( HighPart( temp, WORD ),
                          HighPart( ins->result, WORD ), WORD );
        DupSegRes( ins, ins2 );
        ReplIns( ins, ins2 );
    } else {
        HalfType( ins );
        new_ins = MakeBinary( ins->head.opcode,
                        LowPart( ins->operands[ 0 ], ins->type_class ),
                        LowPart( ins->operands[ 1 ], ins->type_class ),
                        LowPart( ins->result,        ins->type_class ),
                        ins->type_class );
        DupSeg( ins, new_ins );
        ins->operands[ 0 ] = HighPart( ins->operands[ 0 ], ins->type_class );
        ins->operands[ 1 ] = HighPart( ins->operands[ 1 ], ins->type_class );
        ins->result = HighPart( ins->result, ins->type_class );
        if( ins->head.opcode == OP_ADD ) {
            ins->head.opcode = OP_EXT_ADD;
        } else if( ins->head.opcode == OP_SUB ) {
            ins->head.opcode = OP_EXT_SUB;
        }
/* Assign fake reduce table (from OP_EXT) to new_ins; default reduce table
   can generate INC and DEC which'll not set condition codes
 */
        ins->table = CodeTable( ins );
        new_ins->table = ins->table;

        PrefixIns( ins, new_ins );
    }
    new_ins->ins_flags |= INS_CC_USED;
    return( new_ins );
}
Ejemplo n.º 26
0
an      BGCall( cn call, bool use_return, bool in_line )
/******************************************************/
{
    instruction         *call_ins;
    call_state          *state;
    name                *ret_ptr = NULL;
    name                *result;
    name                *temp;
    name                *reg_name;
    instruction         *ret_ins = NULL;
    hw_reg_set          return_reg;
    hw_reg_set          zap_reg;

    if( call->name->tipe == TypeProcParm ) {
        SaveDisplay( OP_PUSH );
    }

    state = call->state;
    result = BGNewTemp( call->tipe );
    call_ins = call->ins;

/*   If we have a return value that won't fit in a register*/
/*   pass a pointer to result as the first parm*/

    if( call_ins->type_class == XX ) {
        if( _RoutineIsFar16( state->attr ) ) {
            if( state->attr & ROUTINE_ALLOCS_RETURN ) {
                HW_CAsgn( state->return_reg, HW_EAX );
            } else {
                HW_CAsgn( state->return_reg, HW_EBX );
            }
        }
        if( ( state->attr & ROUTINE_ALLOCS_RETURN ) == 0 ) {
            if( HW_CEqual( state->return_reg, HW_EMPTY ) ) {
                ret_ptr = AllocTemp( WD );
            } else {
                ret_ptr = AllocRegName( state->return_reg );
            }
            ret_ins = MakeUnary( OP_LA, result, ret_ptr, WD );
            HW_TurnOn( state->parm.used, state->return_reg );
            call_ins->flags.call_flags |= CALL_RETURNS_STRUCT;
        }
    }
    if( _IsTargetModel(FLOATING_DS) && (state->attr&ROUTINE_NEEDS_DS_LOADED) ) {
        HW_CTurnOn( state->parm.used, HW_DS );
    }
    if( _RoutineIsFar16( state->attr ) ) {
#if _TARGET & _TARG_80386
        Far16Parms( call );
#endif
    } else {
        if( AssgnParms( call, in_line ) ) {
            if( state->attr & ROUTINE_REMOVES_PARMS ) {
                call_ins->flags.call_flags |= CALL_POPS_PARMS;
            }
        }
    }

    if( state->attr & (ROUTINE_MODIFIES_NO_MEMORY | ROUTINE_NEVER_RETURNS) ) {
        /* a routine that never returns can not write any memory as far
            as this routine is concerned */
        call_ins->flags.call_flags |= CALL_WRITES_NO_MEMORY;
    }
    if( state->attr & ROUTINE_READS_NO_MEMORY ) {
        call_ins->flags.call_flags |= CALL_READS_NO_MEMORY;
    }
    if( state->attr & ROUTINE_NEVER_RETURNS ) {
        call_ins->flags.call_flags |= CALL_ABORTS;
    }
    if( _RoutineIsInterrupt( state->attr ) ) {
        call_ins->flags.call_flags |= CALL_INTERRUPT | CALL_POPS_PARMS;
    }
    if( !use_return ) {
        call_ins->flags.call_flags |= CALL_IGNORES_RETURN;
    }
    if( call_ins->type_class == XX ) {
        reg_name = AllocRegName( state->return_reg );
        if( state->attr & ROUTINE_ALLOCS_RETURN ) {
            call_ins->result = reg_name;
            AddCall( call_ins, call );
            if( use_return ) {
                temp = AllocTemp( WD ); /* assume near pointer*/
                AddIns( MakeMove( reg_name, temp, WD ) );
                temp = SAllocIndex( temp, NULL, 0,
                                    result->n.type_class, call->tipe->length );
                AddIns( MakeMove( temp, result, result->n.type_class ) );
            }
        } else {
            call_ins->result = result;
            AddIns( ret_ins );
            if( HW_CEqual( state->return_reg, HW_EMPTY ) ) {
                AddIns( MakeUnary( OP_PUSH, ret_ptr, NULL, WD ) );
                state->parm.offset += TypeClassSize[WD];
                call_ins->operands[CALL_OP_POPS] =
                        AllocS32Const( call_ins->operands[CALL_OP_POPS]->c.lo.int_value + TypeClassSize[WD] );
                if( state->attr & ROUTINE_REMOVES_PARMS ) {
                    call_ins->flags.call_flags |= CALL_POPS_PARMS;
                }
            }
            AddCall( call_ins, call );
        }
    } else {
        return_reg = state->return_reg;
        zap_reg = call_ins->zap->reg;
        HW_CTurnOn( zap_reg, HW_FLTS );
        HW_OnlyOn( return_reg, zap_reg );
        call_ins->result = AllocRegName( return_reg );
        reg_name = AllocRegName( state->return_reg );
        AddCall( call_ins, call );
        if( use_return ) {
            ret_ins = MakeMove( reg_name, result, result->n.type_class );
            if( HW_COvlap( reg_name->r.reg, HW_FLTS ) ) {
                ret_ins->stk_entry = 1;
                ret_ins->stk_exit = 0;
            }
            AddIns( ret_ins );
        }
    }
    if( state->parm.offset != 0 && ( state->attr & ROUTINE_REMOVES_PARMS ) == 0 ) {
        reg_name = AllocRegName( HW_SP );
        AddIns( MakeBinary( OP_ADD, reg_name,
                AllocS32Const( state->parm.offset ), reg_name, WD ) );
    }
    return( MakeTempAddr( result ) );
}