i86rtrtn.c

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

C
752
字号
        if( RoutineNum == RT_DPOWI ) {
            parm2_class = I4;
        } else {
            parm2_class = ins->type_class;
        }
        new_ins = MakeUnary( OP_PUSH, ins->operands[ 1 ], NULL, parm2_class );
        MoveSegOp( ins, new_ins, 0 );
        PrefixIns( ins, new_ins );
    }
    reg_name = AllocRegName( all_regs );
    lbl = RTLabel( RoutineNum );
    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;
    if( also_used != NULL ) {
        switch( also_used->n.class ) {
        case N_REGISTER:
        case N_CONSTANT:
            _Zoiks( ZOIKS_047 );
            break;
        case N_MEMORY:
        case N_TEMP:
            also_used->v.usage |= ( USE_MEMORY | NEEDS_MEMORY );
            conf = also_used->v.conflict;
            if( conf != NULL ) {
                InMemory( conf );
            }
            break;
        case N_INDEXED:            /* Dec-20-88*/
            also_used = reg_name;  /* - the index doesn't need an index register!*/
        default:
            break;
        }
        new_ins->operands[ CALL_OP_USED2 ] = also_used;
    } else {
        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*/
    new_ins->zap = &AllocRegName( all_regs )->r;/* all parm regs could be zapped*/
    last_ins = new_ins;
    if( ins->result != NULL ) {
        regs = FirstReg( info->result );
        tmp = regs;
        HW_TurnOn( tmp, new_ins->zap->reg );
        new_ins->zap = &AllocRegName( tmp )->r;
        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 );
    } else {                /* 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;
    }
    UpdateLive( left_ins, last_ins );
    return( left_ins );
}



extern  name    *ScanCall( tbl_control *table, name *value,
                           type_class_def tipe ) {
/*************************************************
    generates a fake call to a rutime routine that looks up "value" in a table
    and jumps to the appropriate case, using either a pointer or index
    returned by the "routine". The "routine" will be generated inline later.
    See BEAuxInfo for the code sequences generated. That will explain
    how the jump destination is determined as well.
*/

    instruction *new_ins;
    name        *reg_name;
    name        *result;
    name        *label;
    hw_reg_set  tmp;
    name        *temp_result;

    switch( tipe ) {
    case U1:
        RoutineNum = RT_SCAN1 - BEG_RTNS;
        break;
    case U2:
        RoutineNum = RT_SCAN2 - BEG_RTNS;
        break;
    case U4:
        RoutineNum = RT_SCAN4 - BEG_RTNS;
        break;
    default:
        break;
    }

    reg_name = AllocRegName( FirstReg( RTInfo[  RoutineNum  ].left ) );
    new_ins = MakeConvert( value, reg_name, tipe, value->n.name_class );
    AddIns( new_ins );

    reg_name = AllocRegName( HW_CX );
    new_ins = MakeMove( AllocRegName( HW_CS ), reg_name, U2 );
    AddIns( new_ins );
    new_ins = MakeMove( reg_name, AllocRegName( HW_ES ), U2 );
    AddIns( new_ins );
    new_ins = MakeMove( AllocIntConst( table->size + 1 ), reg_name, U2 );
    AddIns( new_ins );

    reg_name = AllocRegName( HW_DI );
    if( tipe == U4 ) {
        label = AllocMemory( table, -2, CG_VTB, U2 );
    } else {
        label = AllocMemory( table, 0, CG_VTB, U2 );
    }
    label = AddrConst( label, AskCodeSeg(), CONS_OFFSET );
    new_ins = MakeMove( label, reg_name, U2 );
    AddIns( new_ins );

    new_ins = NewIns( 3 );
    new_ins->head.opcode = OP_CALL;
    new_ins->type_class = U2;
    tmp = FirstReg( RTInfo[ RoutineNum ].left );
    HW_CTurnOn( tmp, HW_ES_DI );
    HW_CTurnOn( tmp, HW_CX );
    new_ins->operands[ CALL_OP_USED ] = AllocRegName( tmp );
    new_ins->operands[ CALL_OP_USED2 ] = new_ins->operands[ CALL_OP_USED ];
    new_ins->operands[ CALL_OP_ADDR ] = AllocMemory( RTLabel(RoutineNum),
                                             0, CG_LBL, U2 );
    new_ins->result = NULL;
    new_ins->num_operands = 2;
    new_ins->zap = &AllocRegName( HW_CX_DI )->r;
    new_ins->result = reg_name;
    AddIns( new_ins );

    result = AllocMemory( table, 0, CG_TBL, U2 ); /* so table gets freed!*/
    if( tipe == U2 ) {
        result = AllocRegName( HW_ES_DI );
        result = AllocIndex( result, NULL, ( table->size - 1 )*2, U2 );
    } else {
        result = AllocIndex( reg_name, result, 0, U2 );
    }
    // this is here because we can get ourselves into trouble
    // by hoisting expressions into the spot between the call and
    // the OP_SELECT instruction at the end of the block if those
    // expressions expand to instructions which require ECX.
    // Same goes for EDI in the U4 case.        BBB - July, 1996
    temp_result = AllocTemp( WD );
    new_ins = MakeMove( result, temp_result, WD );
    AddIns( new_ins );
    return( temp_result );
}


extern  instruction     *rMAKEFNEG( instruction *ins ) {
/*******************************************************
    negating a floating point value which is in the 386 registers only
    needs to change the register containing the exponent, so this is
    handled as a special case rather than using rMAKERTCALL that would
    assume all of the registers containing the number were used
    and modified by the call.
*/

    rtn_info            *info;
    label_handle        lbl;
    instruction         *left_ins;
    instruction         *new_ins;
    instruction         *last_ins;
    name                *reg_name;
    name                *exp_reg;

    LookupRoutine( ins );
    CheckForPCS( ins );
    lbl = RTLabel( RoutineNum );
    info = &RTInfo[  RoutineNum  ];
    reg_name = AllocRegName( FirstReg( info->left ) );
    left_ins = MakeMove( ins->operands[ 0 ], reg_name,
                          info->operand_class );
    ins->operands[ 0 ] = left_ins->result;
    MoveSegOp( ins, left_ins, 0 );
    PrefixIns( ins, left_ins );
    if( ins->type_class == FD ) { /* exponent in AX*/
        exp_reg = AllocRegName( HW_AX );
    } else {                           /* exponent in DX*/
        exp_reg = AllocRegName( HW_DX );
    }
    new_ins = NewIns( 3 );
    new_ins->head.opcode = OP_CALL;
    new_ins->type_class = U2;
    new_ins->operands[ CALL_OP_USED ] = exp_reg;
    new_ins->operands[ CALL_OP_USED2 ] = exp_reg;
    new_ins->operands[ CALL_OP_ADDR ] = AllocMemory( lbl, 0, CG_LBL, U2 );
    new_ins->result = NULL;
    new_ins->num_operands = 2;
    new_ins->zap = &exp_reg->r;
    last_ins = new_ins;
    new_ins->result = exp_reg;
    last_ins = MakeMove( reg_name, ins->result, info->operand_class );
    ins->result = last_ins->operands[ 0 ];
    MoveSegRes( ins, last_ins );
    SuffixIns( ins, last_ins );
    ReplIns( ins, new_ins );
    UpdateLive( left_ins, last_ins );
    return( left_ins );
}


extern  pointer BEAuxInfo( pointer hdl, aux_class request ) {
/************************************************************
    see ScanCall for explanation
*/

    pointer     info = NULL;

    switch( request ) {
    case AUX_LOOKUP:
        switch( FindRTLabel( hdl ) ) {
        case RT_SCAN1:
            info = &Scn1;
            break;
        case RT_SCAN2:
            info = &Scn2;
            break;
        case RT_SCAN4:
            info = &Scn4;
            break;
        default:
            info = NULL;
            break;
        }
        break;
    case CALL_CLASS:
        info = hdl;
        info = &((rt_aux_info *)info)->class;
        break;
    case CALL_BYTES:
        info = hdl;
        info = &((rt_aux_info *)info)->length;
        break;
    default:
        break;
    }
    return( info );
}

⌨️ 快捷键说明

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