rscsplit.c

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

C
1,383
字号
        break;
    case N_REGISTER:
        if( class == U1 || class == I1 ) {
            new = AllocRegName( Low16Reg( tosplit->r.reg ) );
        } else if( class == U2 || class == I2 ) {
            new = AllocRegName( Low32Reg( tosplit->r.reg ) );
        } else {
            new = AllocRegName( Low64Reg( tosplit->r.reg ) );
        }
        break;
    case N_TEMP:
        new = TempOffset( tosplit, 0, class );
        if( new->t.temp_flags & CONST_TEMP ) {
            name *cons = tosplit->v.symbol;
            if( tosplit->n.name_class == FD ) {
                cons = Int64Equivalent( cons );
            }
            new->v.symbol = LowPart( cons, class );
        }
        break;
    case N_MEMORY:
        new = AllocMemory( tosplit->v.symbol, tosplit->v.offset,
                            tosplit->m.memory_type, class );
        new->v.usage = tosplit->v.usage;
        break;
    case N_INDEXED:
        new = ScaleIndex( tosplit->i.index, tosplit->i.base,
                            tosplit->i.constant, class,
                            0, tosplit->i.scale, tosplit->i.index_flags );
        break;
    }
    return( new );
}

extern  name    *HighPart( name *tosplit, type_class_def class )
/***************************************************************
* Return the high (of type 'class') part of name 'tosplit'
* Note: There may not be any need to support splitting to
* classes other than U4/I4 on RISC (assuming that registers are
* at least 32-bit).
*/
{
    name                *new;
    signed_8            s8;
    unsigned_8          u8;
    signed_16           s16;
    unsigned_16         u16;
    unsigned_32         u32;
    constant_defn       *floatval;

    switch( tosplit->n.class ) {
    case N_CONSTANT:
        if( tosplit->c.const_type == CONS_ABSOLUTE ) {
            if( class == U1 ) {
                u8 = ( tosplit->c.int_value >> 8 ) & 0xff;
                new = AllocUIntConst( u8 );
            } else if( class == I1 ) {
                s8 = ( tosplit->c.int_value >> 8 ) & 0xff;
                new = AllocIntConst( s8 );
            } else if( class == U2 ) {
                u16 = ( tosplit->c.int_value >> 16 ) & 0xffff;
                new = AllocUIntConst( u16 );
            } else if( class == I2 ) {
                s16 = ( tosplit->c.int_value >> 16 ) & 0xffff;
                new = AllocIntConst( s16 );
            } else if( class == I4 ) {
                new = AllocS32Const( tosplit->c.int_value_2 );
            } else if( class == U4 ) {
                new = AllocUIntConst( tosplit->c.int_value_2 );
            } else if( class == FL ) {
                _Zoiks( ZOIKS_129 );
            } else { /* FD */
                floatval = GetFloat( tosplit, FD );
                u32 = (unsigned_32)floatval->value[ 3 ] << 16;
                u32 += floatval->value[ 2 ];
                new = AllocConst( CFCnvU32F( _TargetLongInt( u32 ) ) );
            }
#if 0
        } else if( tosplit->c.const_type == CONS_ADDRESS ) {
            new = AddrConst( tosplit->c.value,
                                   tosplit->c.int_value, CONS_SEGMENT );
#endif
        } else {
            _Zoiks( ZOIKS_044 );
        }
        break;
    case N_REGISTER:
        if( class == U1 || class == I1 ) {
            new = AllocRegName( High16Reg( tosplit->r.reg ) );
        } else if( class == U2 || class == I2 ) {
            new = AllocRegName( High32Reg( tosplit->r.reg ) );
        } else {
            new = AllocRegName( High64Reg( tosplit->r.reg ) );
        }
        break;
    case N_TEMP:
        new = TempOffset( tosplit, tosplit->n.size/2, class );
        if( new->t.temp_flags & CONST_TEMP ) {
            name *cons = tosplit->v.symbol;
            if( tosplit->n.name_class == FD ) {
                cons = Int64Equivalent( cons );
            }
            new->v.symbol = HighPart( cons, class );
        }
        break;
    case N_MEMORY:
        new = AllocMemory( tosplit->v.symbol,
                                tosplit->v.offset + tosplit->n.size/2,
                                tosplit->m.memory_type, class );
        new->v.usage = tosplit->v.usage;
        break;
    case N_INDEXED:
        new = ScaleIndex( tosplit->i.index, tosplit->i.base,
                tosplit->i.constant+ tosplit->n.size/2, class,
                0, tosplit->i.scale, tosplit->i.index_flags );
        break;
    }
    return( new );
}

extern  name    *OffsetMem( name *mem, type_length offset, type_class_def tipe ) {
/********************************************************************************/

    name                *new_mem;

    if( mem->n.class == N_INDEXED ) {
        new_mem = ScaleIndex( mem->i.index, mem->i.base,
                        mem->i.constant + offset, mem->n.name_class,
                        TypeClassSize[ tipe ], mem->i.scale, mem->i.index_flags );
    } else {
        assert( mem->n.class == N_TEMP );
        new_mem = STempOffset( mem, offset, tipe, TypeClassSize[ tipe ] );
    }
    return( new_mem );
}

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

    type_class_def      target_type;
    name                *temp_1;
    name                *temp_2;
    instruction         *first_ins;
    instruction         *new_ins;

    // Since sizeof( reg ) > sizeof( int ), we could have junk
    // hanging about in the high 32 bits (or whatever) of the
    // operand. In order to conform to ANSI specs, we have to zero
    // this out, or sign extend the operand if it's a signed
    // shift right. To do this - we make a convert up to 8-byte
    // thing and then convert back down afterwords.

    target_type = U8;
    if( Unsigned[ ins->type_class ] != ins->type_class ) {
        target_type = I8;
    }
    temp_1 = AllocTemp( target_type );
    temp_2 = AllocTemp( target_type );
    first_ins = MakeConvert( ins->operands[ 0 ], temp_1, target_type, ins->type_class );
    PrefixIns( ins, first_ins );
    if( ins->operands[ 1 ]->n.class != N_CONSTANT ) {
        new_ins = MakeConvert( ins->operands[ 1 ], temp_2, target_type, ins->type_class );
        PrefixIns( ins, new_ins );
    } else {
        temp_2 = ins->operands[ 1 ];
    }
    new_ins = MakeBinary( OP_RSHIFT, temp_1, temp_2, temp_1, target_type );
    PrefixIns( ins, new_ins );
    new_ins = MakeConvert( temp_1, ins->result, ins->type_class, target_type );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

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

    name        *temp;
    name        *src;
    name        *dst;
    type_length curr;           // which quad word we are currently on
    type_length size;           // size of the structure
    type_length words;          // number of full quad-word writes to use
    type_length rem;            // number of bytes to write after last quad
    instruction *new_ins;
    instruction *first_ins;
    instruction *last_ins;

    /*
     * Bust up a MOVXX into a series of 4-byte moves - we are guaranteed
     * that both the source and dest are 4-byte aligned.
     */
    assert( ins->operands[ 0 ]->n.class == N_TEMP || ins->operands[ 0 ]->n.class == N_INDEXED );
    temp = AllocTemp( U4 );
    size = ins->operands[ 0 ]->n.size;
    first_ins = NULL;
    last_ins = NULL;
    curr = 0;
    words = size / 4;
    rem = size % 4;
    if( rem ) {
        if( ins->result->n.class == N_TEMP ) {
            if( ( ins->result->t.temp_flags & ALIAS ) == EMPTY ) {
                // we have a write to a struct on the stack which is a master
                // since we don't 'pack' anything into the empty space after
                // this struct, we can safely overwrite it and not bother
                // doing the non-destructive last dword write
                words += 1;
                rem = 0;
            }
        }
    }
    while( words ) {
        src = OffsetMem( ins->operands[ 0 ], curr, U4 );
        dst = OffsetMem( ins->result, curr, U4 );
        curr += 4;
        words -= 1;
        new_ins = MakeMove( src, temp, U4 );
        PrefixIns( ins, new_ins );
        if( first_ins == NULL ) {
            first_ins = new_ins;
        }
        new_ins = MakeMove( temp, dst, U4 );
        if( words == 0 && rem == 0 ) {
            ReplIns( ins, new_ins );
            last_ins = new_ins;
        } else {
            PrefixIns( ins, new_ins );
        }
    }
    switch( rem ) {
    case 0:
        break;
    case 1:
        src = OffsetMem( ins->operands[ 0 ], curr, U1 );
        dst = OffsetMem( ins->result, curr, U1 );
        last_ins = MakeMove( src, temp, U1 );
        if( first_ins == NULL ) {
            first_ins = last_ins;
        }
        ReplIns( ins, last_ins );
        break;
    case 2:
        src = OffsetMem( ins->operands[ 0 ], curr, U2 );
        dst = OffsetMem( ins->result, curr, U2 );
        last_ins = MakeMove( src, temp, U2 );
        if( first_ins == NULL ) {
            first_ins = last_ins;
        }
        ReplIns( ins, last_ins );
        break;
    case 3:
        src = OffsetMem( ins->operands[ 0 ], curr, U1 );
        dst = OffsetMem( ins->result, curr, U1 );
        new_ins = MakeMove( src, temp, U1 );
        PrefixIns( ins, new_ins );
        if( first_ins == NULL ) {
            first_ins = new_ins;
        }
        src = OffsetMem( ins->operands[ 0 ], curr, U2 );
        dst = OffsetMem( ins->result, curr, U2 );
        last_ins = MakeMove( src, temp, U2 );
        ReplIns( ins, last_ins );
        break;
    default:
        assert( 0 );
    }
    UpdateLive( first_ins, last_ins );
    return( first_ins );
}


static  void  CnvOpToInt( instruction * ins, int op )
/***************************************************/
{
    name        *name1;

    switch( ins->type_class ) {
#if 0
    case FS:
        name1 = ins->operands[op];
        if( name1->n.class == N_CONSTANT ) {
            ins->operands[op] = IntEquivalent( name1 );
        }
        break;
#endif
    // this is for the I8 stuff - can't tell what to do in
    // HighPart and LowPart if we don't get rid on constant
    // here
    case FD:
        name1 = ins->operands[op];
        if( name1->n.class == N_CONSTANT ) {
            ins->operands[op] = Int64Equivalent( name1 );
        }
        break;
    default:
        break;
    }
}


static bool IndexOverlaps( instruction *ins, int i )
/**************************************************/
{
    if( ins->operands[ i ]->n.class != N_INDEXED ) return( FALSE );
    if( SameThing( ins->operands[ i ]->i.index, ins->result ) ) return( TRUE );
    return( FALSE );
}

/* Note: This could be used for 128-bit types implemented on top of
 * 64-bit regs or anything along those lines.
 */
#define WORD                U4
#define LONG_WORD           U8
#define HIGH_WORD( x )      ( (x)->c.int_value_2 )

/* NB: The following routines are clones of their Intel counterparts
 * with all segment related junk stripped off.
 */

extern  instruction     *rSPLITOP( instruction *ins )
/****************************************************
* Split a multi-word operation instruction.
*/
{
    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;

⌨️ 快捷键说明

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