Beispiel #1
0
instruction      *rFIXSHIFT( instruction *ins )
/*********************************************/
{
    instruction         *new_ins;
#ifndef NDEBUG
    signed_32           shift_count;
#endif

    /* Fix up shift instructions that try to shift by too large amounts. This
     * can happen when optimizer merges adjacent shift instructions. Arithmetic
     * rights shifts must never exceed (REGISTER_BITS - 1), logical shifts can
     * be replaced with loads of zero constant.
     */
#ifndef NDEBUG
    assert( ins->operands[1]->n.class == N_CONSTANT );
    shift_count = ins->operands[1]->c.lo.int_value;
    assert( shift_count >= REG_SIZE * 8 );
#endif
    if( ins->head.opcode == OP_RSHIFT && Signed[ins->type_class] == ins->type_class ) {
        ins->operands[1] = AllocS32Const( REG_SIZE * 8 - 1 );
        return( ins );
    } else {
        new_ins = MoveConst( 0, ins->result, ins->type_class );
        DupSeg( ins, new_ins );
        ReplIns( ins, new_ins );
        return( new_ins );
    }
}
Beispiel #2
0
static  instruction *KillCompare( instruction *ins, name *result ) {
/******************************************************************/

    instruction *new_ins;

    if( ins->result != NULL ) {
        new_ins = MakeMove( result, ins->result, ins->result->n.type_class );
        DupSeg( ins, new_ins );
        SetCSEBits( ins, new_ins );
        ReplIns( ins, new_ins );
    } else {
        new_ins = ins;
        DoNothing( ins );
    }
    return( new_ins );
}
Beispiel #3
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 );
        }
    }
Beispiel #4
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 );
}
Beispiel #5
0
instruction     *rMAKECALL( instruction *ins )
/*********************************************
    Using the table RTInfo[], do all the necessary stuff to turn
    instruction "ins" into a call to a runtime support routine.  Move
    the parms into registers, and move the return register of the
    runtime routine into the result. Used for 386 and 370 versions
*/
{
    rtn_info            *info;
    label_handle        lbl;
    instruction         *left_ins;
    instruction         *new_ins;
    instruction         *last_ins;
    name                *reg_name;
    hw_reg_set          regs;
    hw_reg_set          all_regs;
    hw_reg_set          tmp;
    rt_class            rtindex;

    if( !_IsConvert( ins ) ) {
        rtindex = LookupRoutine( ins );
    } else { /* look it up again in case we ran out of memory during expansion*/
        rtindex = LookupConvertRoutine( ins );
    }
    info = &RTInfo[rtindex];
    regs = _ParmReg( info->left );
    all_regs = regs;
    left_ins = MakeMove( ins->operands[0], AllocRegName( regs ),
                          info->operand_class );
    ins->operands[0] = left_ins->result;
    MoveSegOp( ins, left_ins, 0 );
    PrefixIns( ins, left_ins );
    regs = _ParmReg( info->right );
    if( !HW_CEqual( regs, HW_EMPTY ) ) {
        new_ins = MakeMove( ins->operands[1], AllocRegName( regs ),
                                info->operand_class );
        ins->operands[1] = new_ins->result;
        MoveSegOp( ins, new_ins, 0 );
        HW_TurnOn( all_regs, regs );
        PrefixIns( ins, new_ins );
    }
#if _TARGET & _TARG_370
    tmp = RAReg();
    HW_TurnOn( all_regs, tmp );
    tmp = LNReg();
    HW_TurnOn( all_regs, tmp );
#elif _TARGET & _TARG_80386
    {
    tmp = ReturnReg( WD, false );
    HW_TurnOn( all_regs, tmp );
    }
#endif
    reg_name = AllocRegName( all_regs );
    lbl = RTLabel( rtindex );
    new_ins = NewIns( 3 );
    new_ins->head.opcode = OP_CALL;
    new_ins->type_class = ins->type_class;
    new_ins->operands[CALL_OP_USED] = reg_name;
    new_ins->operands[CALL_OP_USED2] = reg_name;
    new_ins->operands[CALL_OP_ADDR] = AllocMemory( lbl, 0, CG_LBL, ins->type_class );
    new_ins->result = NULL;
    new_ins->num_operands = 2;         /* special case for OP_CALL*/
#if _TARGET & _TARG_AXP
    {
    HW_CTurnOn( all_regs, HW_FULL );
    HW_TurnOff( all_regs, SavedRegs() );
    HW_CTurnOff( all_regs, HW_UNUSED );
    HW_TurnOn( all_regs, ReturnAddrReg() );
    }
#endif
    new_ins->zap = (register_name *)AllocRegName( all_regs );   /* all parm regs could be zapped*/
    last_ins = new_ins;
    if( ins->result == NULL || _OpIsCondition( ins->head.opcode ) ) {
        /* comparison, still need conditional jumps*/
        ins->operands[0] = AllocIntConst( 0 );
        ins->operands[1] = AllocIntConst( 1 );
        DelSeg( ins );
        DoNothing( ins );               /* just conditional jumps for ins*/
        PrefixIns( ins, new_ins );
        new_ins->ins_flags |= INS_CC_USED;
        last_ins = ins;
    } else {
        regs = _ParmReg( info->result );
        tmp = regs;
        HW_TurnOn( tmp, new_ins->zap->reg );
        new_ins->zap = (register_name *)AllocRegName( tmp );
        reg_name = AllocRegName( regs );
        new_ins->result = reg_name;
        last_ins = MakeMove( reg_name, ins->result, ins->type_class );
        ins->result = last_ins->operands[0];
        MoveSegRes( ins, last_ins );
        SuffixIns( ins, last_ins );
        ReplIns( ins, new_ins );
    }
    FixCallIns( new_ins );
    UpdateLive( left_ins, last_ins );
    return( left_ins );
}
Beispiel #6
0
static  instruction    *FoldAbsolute( instruction *ins ) {
/*********************************************************
    See below.
*/
    instruction *new_ins;
    opcnt       num_operands;
    name        *result;
    tn          fold;
    type_def    *tipe;
    type_def    *left_tipe;
    type_def    *rite_tipe;
    type_def    *fold_tipe;
    pointer     left;
    pointer     rite;
    name        *tmp;
    name        *new_const;
    float_handle value;

    tipe = ClassType( ins->type_class );
    left_tipe = ClassType( _OpClass( ins ) );
    num_operands = OpcodeNumOperands( ins );
    left = NULL;
    rite = NULL;
    if( num_operands != 0 ) {
        left = TName( ins->operands[0], left_tipe );
        if( num_operands > 1 ) {
            if( ins->operands[1]->n.type_class == XX ) {
                rite_tipe = tipe;
            } else {
                rite_tipe = ClassType( ins->operands[1]->n.type_class );
            }
            rite = TName( ins->operands[1], rite_tipe );
        }
    }
    fold = NULL;
    switch( ins->head.opcode ) {
    case OP_ADD:
        fold = FoldPlus( left, rite, tipe );
        break;
    case OP_SUB:
        fold = FoldMinus( left, rite, tipe );
        break;
    case OP_MUL:
        fold = FoldTimes( left, rite, tipe );
        break;
    case OP_DIV:
        fold = FoldDiv( left, rite, tipe );
        break;
    case OP_MOD:
        fold = FoldMod( left, rite, tipe );
        break;
    case OP_AND:
        fold = FoldAnd( left, rite, tipe );
        break;
    case OP_OR:
        fold = FoldOr( left, rite, tipe );
        break;
    case OP_XOR:
        fold = FoldXor( left, rite, tipe );
        break;
    case OP_RSHIFT:
        fold = FoldRShift( left, rite, tipe );
        break;
    case OP_LSHIFT:
        fold = FoldLShift( left, rite, tipe );
        break;
    case OP_NEGATE:
        fold = FoldUMinus( left, tipe );
        break;
    case OP_COMPLEMENT:
        fold = Fold1sComp( left, tipe );
        break;
    case OP_CONVERT:
        // look out for CNV PT U2 t1 type instructions; if sizeof( PT ) is greater
        // than sizeof( U2 ), we don't want to fold or we'll screw up based pointers
        if( IsTrickyPointerConv( ins ) )
            return( NULL );
        // fall through!
    case OP_ROUND:
        fold = FoldCnvRnd( (cg_op)ins->head.opcode, left, tipe );
        break;
    case OP_CMP_EQUAL:
    case OP_CMP_NOT_EQUAL:
    case OP_CMP_GREATER:
    case OP_CMP_LESS_EQUAL:
    case OP_CMP_LESS:
    case OP_CMP_GREATER_EQUAL:
        if( ActiveCompare( ins ) ) {
            fold = FoldCompare( (cg_op)ins->head.opcode, left, rite, tipe );
            if( fold != NULL ) {
                return( StraightLine( ins, fold, true ) );
            }
        }
        break;
    case OP_BIT_TEST_TRUE:
        if( ActiveCompare( ins ) ) {
            fold = FoldAnd( left, rite, tipe );
            if( fold != NULL ) {
                return( StraightLine( ins, fold, true ) );
            }
        }
        break;
    case OP_BIT_TEST_FALSE:
        if( ActiveCompare( ins ) ) {
            fold = FoldAnd( left, rite, tipe );
            if( fold != NULL ) {
                return( StraightLine( ins, fold, false ) );
            }
        }
        break;
    default:
        fold = NULL;
        break;
    }
    if( fold != NULL ) {
        fold_tipe = fold->tipe;
        result = TGetName( fold );
        if( result != NULL && !NeedConvert( fold_tipe, tipe ) ) {
            ins->table = NULL;
            // look out for scary DIV U4 EDX:EAX, c1 -> t1 type instructions
            if( result->n.class != N_CONSTANT &&
                result->n.size != TypeClassSize[ins->type_class] )
                return( NULL );
            // look out for scary MUL U4 EDX:EAX, c1 -> t1 type instructions
            if( result->n.class != N_CONSTANT &&
                ins->result->n.size != TypeClassSize[ins->type_class] )
                return( NULL );
            new_ins = MakeMove( result, ins->result, ins->type_class );
            SetCSEBits( ins, new_ins );
            DupSeg( ins, new_ins );
            ReplIns( ins, new_ins );
            return( new_ins );
        }