axpsplit.c

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

C
703
字号
extern  instruction     *rSTORE_4U( instruction *ins ) {
/******************************************************/

    instruction         *first_ins;
    instruction         *new_ins;
    name                *high;
    name                *low;
    name                *temp_high;
    name                *temp_low;
    name                *addr;
    name                *mem_high;
    name                *mem_low;
    name                *value;

    mem_low =  OffsetMem( ins->result, 0, U8 );
    mem_high = OffsetMem( ins->result, 3, U8 );
    value = AllocTemp( U8 );
    addr = AllocTemp( U8 );
    high = AllocTemp( U8 );
    low = AllocTemp( U8 );
    temp_high = AllocTemp( U8 );
    temp_low = AllocTemp( U8 );
    first_ins = MakeConvert( ins->operands[ 0 ], value, U8, ins->type_class );
    PrefixIns( ins, first_ins );
    new_ins = MakeUnary( OP_LA, mem_low, addr, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_high, high, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_low, low, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_INSERT_HIGH, value, addr, temp_high, U8, U4, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_INSERT_LOW, value, addr, temp_low, U8, U4, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_MASK_HIGH, high, addr, high, U8, U4, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeNary( OP_MASK_LOW, low, addr, low, U8, U4, 2 );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_OR, high, temp_high, high, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeBinary( OP_OR, low, temp_low, low, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_STORE_UNALIGNED, high, mem_high, U8 );
    PrefixIns( ins, new_ins );
    new_ins = MakeUnary( OP_STORE_UNALIGNED, low, mem_low, U8 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}

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

    _Zoiks( ZOIKS_091 );
    return( ins );
}

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

    _Zoiks( ZOIKS_091 );
    return( ins );
}

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

    name        *bit_mask;
    name        *temp;
    name        *temp_2;
    name        *src;
    name        *dst;
    type_length curr;           // which quad word we are currently on
    type_length size;           // size of the structure
    type_length quads;          // 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 8-byte moves - we are guaranteed
     * that both the source and dest are 8-byte aligned.
     */
    assert( ins->operands[ 0 ]->n.class == N_TEMP || ins->operands[ 0 ]->n.class == N_INDEXED );
    temp = AllocTemp( U8 );
    size = ins->operands[ 0 ]->n.size;
    first_ins = NULL;
    last_ins = NULL;
    curr = 0;
    quads = size / 8;
    rem = size % 8;
    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 quad-word write
                quads += 1;
                rem = 0;
            }
        }
    }
    while( quads ) {
        src = OffsetMem( ins->operands[ 0 ], curr, U8 );
        dst = OffsetMem( ins->result, curr, U8 );
        curr += 8;
        quads -= 1;
        new_ins = MakeMove( src, temp, U8 );
        PrefixIns( ins, new_ins );
        if( first_ins == NULL ) {
            first_ins = new_ins;
        }
        new_ins = MakeMove( temp, dst, U8 );
        if( quads == 0 && rem == 0 ) {
            ReplIns( ins, new_ins );
            last_ins = new_ins;
        } else {
            PrefixIns( ins, new_ins );
        }
    }
    if( rem != 0 ) {
        if( rem == 4 ) {
            src = OffsetMem( ins->operands[ 0 ], curr, U4 );
            dst = OffsetMem( ins->result, curr, U4 );
            temp_2 = AllocTemp( U4 );
            new_ins = MakeMove( src, temp_2, U4 );
            PrefixIns( ins, new_ins );
            if( first_ins == NULL ) {
                first_ins = new_ins;
            }
            new_ins = MakeMove( temp_2, dst, U4 );
            ReplIns( ins, new_ins );
            last_ins = new_ins;
        } else {
            src = OffsetMem( ins->operands[ 0 ], curr, U8 );
            dst = OffsetMem( ins->result, curr, U8 );
            temp_2 = AllocTemp( U8 );
            bit_mask = AllocS32Const( ( 1 << rem ) - 1 );
            new_ins = MakeMove( src, temp, U8 );
            PrefixIns( ins, new_ins );
            if( first_ins == NULL ) {
                first_ins = new_ins;
            }
            new_ins = MakeMove( dst, temp_2, U8 );
            PrefixIns( ins, new_ins );
            new_ins = MakeBinary( OP_ZAP_NOT, temp, bit_mask, temp, U8 );
            PrefixIns( ins, new_ins );
            new_ins = MakeBinary( OP_ZAP, temp_2, bit_mask, temp_2, U8 );
            PrefixIns( ins, new_ins );
            new_ins = MakeBinary( OP_OR, temp_2, temp, temp, U8 );
            PrefixIns( ins, new_ins );
            new_ins = MakeMove( temp, dst, U8 );
            ReplIns( ins, new_ins );
            last_ins = new_ins;
        }

    }
    UpdateLive( first_ins, last_ins );
    return( first_ins );
}

#if 0
extern instruction      *rCONSTLOAD( instruction *ins ) {
/*******************************************************/
    signed_16           high;
    signed_16           low;
    signed_16           extra;

    assert( ins->operands[ 0 ]->n.class == N_CONSTANT );
    assert( ins->operands[ 0 ]->c.const_type == CONS_ABSOLUTE );

    first = NULL;
    FactorInt32( ins->operands[ 0 ]->c.int_value, &high, &extra, &low );
    // work to be done here - need some way of accurately representing
    // the ldah rn,extra(rn) instruction
}
#else
extern instruction      *rCONSTLOAD( instruction *ins ) {
/*******************************************************/

    instruction         *new_ins;
    instruction         *first_ins;
    name                *high_part;
    name                *low_part;
    name                *temp;
    name                *cons;
    unsigned_32         high;
    unsigned_32         low;
    unsigned_32         k;
    unsigned_32         c;
    type_class_def      index_class;
    bool                cruft_in_high_dword;

    assert( ins->operands[ 0 ]->n.class == N_CONSTANT );
    assert( ins->operands[ 0 ]->c.const_type == CONS_ABSOLUTE );

    cons = ins->operands[ 0 ];
    c = cons->c.int_value;
    k = 65536U;
    high = c / k;
    low = c % k;
    if( low >= ( k / 2 ) ) {
        high += 1;
        low -= k;
    }
    assert( ( (signed_16)high * k + (signed_16)low ) == c );
    high_part = AllocAddrConst( NULL, high, CONS_HIGH_ADDR, ins->type_class );
    if( low == 0 ) {
        first_ins = MakeMove( high_part, ins->result, ins->type_class );
        ReplIns( ins, first_ins );
        if( ( c & 0x80000000 ) &&
            ( first_ins->type_class == Unsigned[ first_ins->type_class ] ) ) {
            new_ins = MakeBinary( OP_ZAP_NOT, first_ins->result, AllocS32Const( 0x0f ), first_ins->result, first_ins->type_class );
            SuffixIns( first_ins, new_ins );
            UpdateLive( first_ins, new_ins );
        }
    } else {
        index_class = I4;
        temp = AllocTemp( index_class );
        first_ins = MakeMove( high_part, temp, index_class );
        PrefixIns( ins, first_ins );
        low_part = AllocIndex( temp, NULL, low, ins->type_class );
        new_ins = MakeUnary( OP_LA, low_part, ins->result, ins->type_class );
        PrefixIns( ins, new_ins );
        cruft_in_high_dword = FALSE;
        if( c >= 0x7fff8000 && c <= 0x7fffffff ) {
            cruft_in_high_dword = TRUE;
        }
        if( ( c & 0x80000000 ) &&
            ( ins->type_class == Unsigned[ ins->type_class ] ) ) {
            cruft_in_high_dword = TRUE;
        }
        if( cruft_in_high_dword ) {
            new_ins = MakeBinary( OP_ZAP_NOT, ins->result, AllocS32Const( 0x0f ), ins->result, ins->type_class );
            PrefixIns( ins, new_ins );
        }
        FreeIns( ins );
        UpdateLive( first_ins, new_ins );
    }
    return( first_ins );
}
#endif

static instruction *CheapCall( instruction *ins, int rt_call, name *p1, name *p2 ) {
/**********************************************************************************/

    instruction         *call;
    hw_reg_set          reg;
    name                *reg_name;
    label_handle        lbl;

    reg = HW_EMPTY;
    lbl = RTLabel( rt_call );
    call = NewIns( 3 );
    call->head.opcode = OP_CALL;
    call->type_class = WD;
    call->operands[ CALL_OP_USED ] = p1;
    call->operands[ CALL_OP_USED2 ] = p2;
    call->operands[ CALL_OP_ADDR ]= AllocMemory( lbl, 0, CG_LBL, WD );
    call->result = NULL;
    call->num_operands = 2;         /* special case for OP_CALL*/
    HW_TurnOn( reg, ReturnAddrReg() );
    HW_TurnOn( reg, ScratchReg() );
    HW_CTurnOn( reg, HW_R1 );   // know this is only other reg modified!
    HW_CTurnOn( reg, HW_R2 );   // and this one two!
    HW_CTurnOn( reg, HW_R3 );   // and this one three!
    reg_name = AllocRegName( reg );
    call->zap = &reg_name->r;
    PrefixIns( ins, call );
    return( call );
}

static void CopyStack( instruction *ins, name *alloc_size, type_length arg_size ) {
/*********************************************************************************/

    instruction         *new_ins;
    name                *p1;
    name                *p2;

    p1 = AllocRegName( HW_D1 );
    new_ins = MakeMove( alloc_size, p1, WD );
    PrefixIns( ins, new_ins );
    p2 = AllocRegName( HW_D2 );
    new_ins = MakeMove( AllocS32Const( arg_size ), p2, WD );
    PrefixIns( ins, new_ins );
    CheapCall( ins, RT_STK_COPY, p1, p2 );
}

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

    name                *sreg;
    name                *amount;
    name                *real_amount;
    name                *temp;
    unsigned_32         value;
    instruction         *first;
    instruction         *last;
    type_class_def      class;
    unsigned_32         stack_align;
    bool                check;

    sreg = AllocRegName( StackReg() );
    amount = ins->operands[ 0 ];
    temp = AllocTemp( ins->type_class );
    class = WD;
    stack_align = STACK_ALIGNMENT;
    check = TRUE;
    CurrProc->targ.base_is_fp = TRUE;
    if( amount->n.class == N_CONSTANT && amount->c.const_type == CONS_ABSOLUTE ) {
        value = amount->c.int_value;
        value = _RoundUp( value, stack_align );
        real_amount = AllocS32Const( value );
        first = MakeBinary( OP_SUB, sreg, AllocS32Const( value ), temp, class );
        PrefixIns( ins, first );
        if( value <= ( PAGE_SIZE - 7 ) ) {
            check = FALSE;
        }
    } else {
        real_amount = AllocTemp( ins->type_class );
        first = MakeBinary( OP_ADD, amount, AllocS32Const( stack_align - 1 ), temp, class );
        PrefixIns( ins, first );
        last = MakeBinary( OP_AND, temp, AllocS32Const( ~( stack_align - 1 ) ), real_amount, class );
        PrefixIns( ins, last );
        last = MakeBinary( OP_SUB, sreg, real_amount, temp, class );
        PrefixIns( ins, last );
    }
    last = MakeMove( temp, sreg, WD );
    PrefixIns( ins, last );
    if( check ) {
        CheapCall( ins, RT_STK_CRAWL, AllocRegName( HW_EMPTY ), AllocRegName( HW_EMPTY ) );
    }
    if( MaxStack != 0 ) {
        if( _IsModel( MICROSOFT_COMPATIBLE ) ) {
            // in order to support doing alloca's in parm lists, we copy
            // the parm cache area down now
            CopyStack( ins, real_amount, MaxStack );

        }
        last = MakeBinary( OP_ADD, temp, AllocS32Const( MaxStack ), ins->result, class );
    } else {
        last = MakeMove( temp, ins->result, class );
    }
    ReplIns( ins, last );
    UpdateLive( first, last );
    return( first );

}

⌨️ 快捷键说明

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