mipssplit.c

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

C
427
字号
/**********************************************/
{
    instruction         *first_ins;
    instruction         *new_ins;
    name                *mem_1;
    name                *mem_2;
    name                *temp;

    mem_1 = OffsetMem( ins->operands[0], 3, U4 );
    mem_2 = OffsetMem( ins->operands[0], 0, U4 );
    temp = AllocTemp( U4 );
    first_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_1, temp, U4 );
    PrefixIns( ins, first_ins );
    new_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_2, temp, U4 );
    PrefixIns( ins, new_ins );
    new_ins = MakeMove( temp, ins->result, U4 );
    ReplIns( ins, new_ins );
    UpdateLive( first_ins, new_ins );
    return( first_ins );
}


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() );
    // TODO: these regs are most likely wrong for MIPS
    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 );
}


/* MIPS is a little weird - it only has 'set' instruction for
 * 'less than' (reg/reg and reg/imm variants). Conditional branch
 * instructions can't take an immediate operand (except $zero of course)
 * and there isn't a full set of reg/reg conditional branches. So we
 * have to carefully reduce the instructions here...
 * NB: This is a clone of rSIMPCMP from rscsplit.c
 */
extern instruction      *rM_SIMPCMP( instruction *ins )
/******************************************************/
{
    instruction         *new;
    opcode_defs         opcode;
    bool                reverse;

    reverse = FALSE;
    assert( ins->result == NULL );
    switch( ins->head.opcode ) {
    case OP_CMP_NOT_EQUAL:
        reverse = TRUE;
        /* fall through */
    case OP_CMP_EQUAL:
        opcode = OP_SET_EQUAL;
        break;
    case OP_CMP_GREATER:
        reverse = TRUE;
        /* fall through */
    case OP_CMP_LESS_EQUAL:
        opcode = OP_SET_LESS_EQUAL;
        /* Special reduction: use OP_SET_LESS but increment constant */
        if( (ins->operands[1]->n.class == N_CONSTANT)
            && (ins->operands[1]->c.const_type == CONS_ABSOLUTE) ) {
            signed_32           value;

            opcode = OP_SET_LESS;
            // TODO: we may be leaking memory here by losing track of the
            // original constant operand
            value = ins->operands[1]->c.int_value;
            ins->operands[1] = AllocS32Const( value + 1 );
        }
        if( ins->operands[1]->n.class == N_REGISTER ) {
            // Swap operands and reverse condition - we can do slt/sltu but
            // nothing else
            return( rSWAPCMP( ins ) );
        }
        break;
    case OP_CMP_GREATER_EQUAL:
        reverse = TRUE;
        /* fall through */
    case OP_CMP_LESS:
        opcode = OP_SET_LESS;
        break;
    }
    ins->result = AllocTemp( ins->type_class );
    switch( ins->type_class ) {
    case I4:
    case U4:
        ins->table = OpcodeTable( BIN4 );
        break;
    case I8:
    case U8:
        ins->table = OpcodeTable( BIN8 );
        break;
    case FS:
        ins->table = OpcodeTable( FBINS );
        break;
    case FD:
    case FL:
        ins->table = OpcodeTable( FBIND );
        break;
    default:
        _Zoiks( ZOIKS_096 );
    }
    ins->head.opcode = opcode;
    opcode = OP_CMP_NOT_EQUAL;
    if( reverse ) {
        opcode = OP_CMP_EQUAL;
    }
    new = MakeCondition( opcode, ins->result, AllocS32Const( 0 ), _TrueIndex( ins ), _FalseIndex( ins ), ins->type_class );
    SuffixIns( ins, new );
    return( new );
}

⌨️ 快捷键说明

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