i86half.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 456 行 · 第 1/2 页

C
456
字号
extern  instruction     *rMAKEU2( instruction *ins ) {
/***************************************************/

    instruction *new_ins;
    instruction *ins2;
    name        *temp = NULL;

    if( IndexOverlaps( ins, 0 ) || IndexOverlaps( ins, 1 ) ) {
        ChangeType( ins, WORD );
        if( ins->result != NULL ) {
            new_ins = MakeMove( HighPart( ins->operands[ 0 ], WORD ),
                                 AllocTemp( WORD ), WORD );
            temp = HighPart( ins->result, WORD );
            ins->result = LowPart( ins->result, WORD );
            DupSegOp( ins, new_ins, 0 );
            PrefixIns( ins, new_ins );
        } else {
            new_ins = ins;
        }
        ins->operands[ 0 ] = LowPart( ins->operands[ 0 ], WORD );
        if( ins->operands[ 1 ]->n.name_class == LONG_WORD
         || ins->operands[ 1 ]->n.name_class == LONG_WORD_S ) {
            ins->operands[ 1 ] = LowPart( ins->operands[ 1 ], WORD );
        }
        if( ins->result != NULL ) {
            ins2 = MakeMove( new_ins->result, temp, WORD );
            DupSegRes( ins, ins2 );
            SuffixIns( ins, ins2 );
        }
    } else {
        ChangeType( ins, WORD );
        if( ins->result != NULL ) {
            new_ins = MakeMove( HighPart( ins->operands[ 0 ], WORD ),
                                 HighPart( ins->result, WORD ), WORD );
            ins->result = LowPart( ins->result, WORD );
            DupSegOp( ins, new_ins, 0 );
            DupSegRes( ins, new_ins );
            PrefixIns( ins, new_ins );
        } else {
            new_ins = ins;
        }
        ins->operands[ 0 ] = LowPart( ins->operands[ 0 ], WORD );
        ins->operands[ 1 ] = LowPart( ins->operands[ 1 ], WORD );
    }
    return( new_ins );
}
#endif

extern  instruction     *rSPLITNEG( instruction *ins ) {
/******************************************************/

    name        *hi_res;
    name        *lo_res;
    name        *hi_src;
    name        *lo_src;
    instruction *hi_ins;
    instruction *lo_ins;
    instruction *subtract;

    HalfType( ins );
    hi_res = HighPart( ins->result, ins->type_class );
    hi_src = HighPart( ins->operands[ 0 ], ins->type_class );
    lo_res = LowPart( ins->result, ins->type_class );
    lo_src = LowPart( ins->operands[ 0 ], ins->type_class );
    hi_ins = MakeUnary( OP_NEGATE, hi_src, hi_res, ins->type_class );
    lo_ins = MakeUnary( OP_NEGATE, lo_src, lo_res, ins->type_class );
    lo_ins->ins_flags |= INS_CC_USED;
    subtract = MakeBinary( OP_EXT_SUB, hi_res, AllocIntConst( 0 ), hi_res,
                            ins->type_class );
    DupSegRes( ins, subtract );
    DupSeg( ins, hi_ins );
    DupSeg( ins, lo_ins );
    PrefixIns( ins, hi_ins );
    ins->operands[ 0 ] = ins->result;
    ins->operands[ 1 ] = AllocIntConst( 0 );
    PrefixIns( ins, lo_ins );
    ReplIns( ins, subtract );
    UpdateLive( hi_ins, subtract );
    return( hi_ins );
}

extern  instruction     *rSPLITCMP( instruction *ins ) {
/*********************************************************/

    name                *left;
    name                *right;
    instruction         *low = NULL;
    instruction         *high = NULL;
    instruction         *not_equal = NULL;
    type_class_def      high_class;
    type_class_def      low_class;
    byte                true_idx;
    byte                false_idx;

    high_class = HalfClass[  ins->type_class  ];
    low_class  = Unsigned[  high_class  ];
    left = ins->operands[ 0 ];
    right = ins->operands[ 1 ];
    true_idx = _TrueIndex( ins );
    false_idx = _FalseIndex( ins );
    switch( ins->head.opcode ) {
    case OP_BIT_TEST_TRUE:
        high = MakeCondition( ins->head.opcode,
                        HighPart( left, high_class ),
                        HighPart( right, high_class ),
                        true_idx, NO_JUMP,
                        WORD );
        low = MakeCondition( ins->head.opcode,
                        LowPart( left, low_class ),
                        LowPart( right, low_class ),
                        true_idx, false_idx,
                        WORD );
        not_equal = NULL;
        break;
    case OP_BIT_TEST_FALSE:
        high = MakeCondition( OP_BIT_TEST_TRUE,
                        HighPart( left, high_class ),
                        HighPart( right, high_class ),
                        false_idx, NO_JUMP,
                        WORD );
        low = MakeCondition( ins->head.opcode,
                        LowPart( left, low_class ),
                        LowPart( right, low_class ),
                        true_idx, false_idx,
                        WORD );
        not_equal = NULL;
        break;
    case OP_CMP_EQUAL:
        high = MakeCondition( OP_CMP_NOT_EQUAL,
                        HighPart( left, high_class ),
                        HighPart( right, high_class ),
                        false_idx, NO_JUMP,
                        WORD );
        low = MakeCondition( ins->head.opcode,
                        LowPart( left, low_class ),
                        LowPart( right, low_class ),
                        true_idx, false_idx,
                        WORD );
        not_equal = NULL;
        break;
    case OP_CMP_NOT_EQUAL:
        high = MakeCondition( OP_CMP_NOT_EQUAL,
                        HighPart( left, high_class ),
                        HighPart( right, high_class ),
                        true_idx, NO_JUMP,
                        WORD );
        low = MakeCondition( ins->head.opcode,
                        LowPart( left, low_class ),
                        LowPart( right, low_class ),
                        true_idx, false_idx,
                        WORD );
        not_equal = NULL;
        break;
    case OP_CMP_LESS:
    case OP_CMP_LESS_EQUAL:
        not_equal = MakeCondition( OP_CMP_NOT_EQUAL,
                        HighPart( left, high_class ),
                        HighPart( right, high_class ),
                        false_idx, NO_JUMP,
                        high_class );
        if( high_class == WORD
         && right->n.class == N_CONSTANT
         && right->c.const_type == CONS_ABSOLUTE
         && HIGH_WORD( right ) == 0 ) {
            high = NULL;
        } else {
            high = MakeCondition( OP_CMP_LESS,
                        not_equal->operands[ 0 ], not_equal->operands[ 1 ],
                        true_idx, NO_JUMP,
                        high_class );
        }
        low = MakeCondition( ins->head.opcode,
                        LowPart( left, low_class ),
                        LowPart( right, low_class ),
                        true_idx, false_idx,
                        low_class );
        break;
    case OP_CMP_GREATER_EQUAL:
    case OP_CMP_GREATER:
        not_equal = MakeCondition( OP_CMP_NOT_EQUAL,
                        HighPart( left, high_class ),
                        HighPart( right, high_class ),
                        false_idx, NO_JUMP,
                        high_class );
        if( high_class == WORD
         && right->n.class == N_CONSTANT
         && right->c.const_type == CONS_ABSOLUTE
         && HIGH_WORD( right ) == 0 ) {
            _SetBlockIndex( not_equal, true_idx, NO_JUMP );
            high = NULL;
        } else {
            high = MakeCondition( OP_CMP_GREATER,
                        not_equal->operands[ 0 ], not_equal->operands[ 1 ],
                        true_idx, NO_JUMP,
                        high_class );
        }
        low = MakeCondition( ins->head.opcode,
                        LowPart( left, low_class ),
                        LowPart( right, low_class ),
                        true_idx, false_idx,
                        low_class );
        break;
    default:
        break;
    }
    if( high != NULL ) {
/*
 * 2005-04-06 RomanT (bug #407)
 * I removed calls do DoNothing(), it seems ok, extra jumps are perfectly
 * optimized out in other places of compiler. Calling DoNothing() on chain
 * of conditions to reuse existing CC flags is ugly and causes unpredictable
 * logical faults in other places.
 */
        DupSeg( ins, high );
        PrefixIns( ins, high );
    } else {
        high = not_equal;              /* for return value*/
    }
    if( not_equal != NULL ) {
        DupSeg( ins, not_equal );
        PrefixIns( ins, not_equal );
    }
    DupSeg( ins, low );
    ReplIns( ins, low );
    return( high );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?