i86rtrtn.c

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

C
752
字号

static  rt_aux_info Scn4 = {
                        0, 18,
                       {0x83, 0xC7, 0x02,       /* L1:   add     d1,2*/
                        0x49,                   /* L2:   dec     cx*/
                        0x74, 0x08,             /*       je      L3*/
                        0xAF,                   /*       scasw*/
                        0x75, 0xF7,             /*       jne     L1*/
                        0x92,                   /*       xchg    dx,ax*/
                        0xAF,                   /*       scasw*/
                        0x92,                   /*       xchg    dx,ax*/
                        0x75, 0xF5,             /*       jne     L2*/
                        0xD1, 0xE1,             /* L3:   shl     cx,1*/
                        0x89, 0xCF}             /*       mov     di,cx*/
                        };

#include "cgrealgn.h"

extern  char    *AskRTName( int rtindex ) {
/*****************************************/

    return( RTInfo[  rtindex  ].nam );
}


static  hw_reg_set      FirstReg( reg_set_index index ) {
/********************************************************
    the tables above use RL_ consts rather that hw_reg_sets cause
    it cheaper. This just picks off the first register from a
    register list and returns it.
*/

    hw_reg_set  *list;

    list = RegSets[  index  ];
    return( *list );
}


extern  name    *Addressable( name *cons, type_class_def class ) {
/*****************************************************************
    make sure a floating point constant is addressable (dropped
    it into memory if it isnt)
*/
    unsigned_64         buffer;

    if( cons->n.class == N_CONSTANT ) {
        switch( class ) {
        case FD:
        case FS:
            return( GenFloat( cons, class ) );
        case U8:
        case I8:
            buffer.u._32[ I64LO32 ] = cons->c.int_value;
            buffer.u._32[ I64HI32 ] = cons->c.int_value_2;
            return( GenConstData( (byte *)&buffer, class ) );
        default:
            Zoiks( ZOIKS_138 );
            break;
        }
        return( GenFloat( cons, class ) );
    }
    return( cons );
}


static void CheckForPCS( instruction *ins ) {
/********************************************
    check to see if pointer subtract is really pointer - pointer
    or pointer - integer (PCS = Pointer Constant Subtract)
*/

    if( RoutineNum + BEG_RTNS == RT_PTS ) {
        if( ins->operands[ 1 ]->n.name_class != PT
         && ins->operands[ 1 ]->n.name_class != CP ) {
            RoutineNum = RT_PCS - BEG_RTNS;
        }
    }
}


extern  bool    RTLeaveOp2( instruction *ins ) {
/***********************************************
    return true if it's a bad idea to put op2 into a temporary since we're
    gonna take the bugger's address in rMAKECALL anyway for FDD, FDC, EDA, etc
*/
    switch( ins->type_class ) {
    case FD:
        if( _FPULevel( FPU_87 ) ) return( FALSE );
        break;
    case I8:
    case U8:
        break;
    default:
        return( FALSE );
    }
    if( NumOperands( ins ) != 2 ) return( FALSE );
    return( TRUE );
}


static  void    FlipIns( instruction *ins ) {
/********************************************
   maybe flip the const/mem into the second operand so it goes in local data
*/
    name        *temp;

    switch( ins->head.opcode ) {
    case OP_ADD:
    case OP_MUL:
        break;
    default:
        return;
    }
    switch( ins->type_class ) {
    case FD:
    case I8:
    case U8:
        break;
    default:
        return;
    }
    temp = ins->operands[ 0 ];
    if( temp->n.class == N_CONSTANT
     || temp->n.class == N_MEMORY
     || temp->n.class == N_INDEXED ) {
        ins->operands[ 0 ] = ins->operands[ 1 ];
        ins->operands[ 1 ] = temp;
    }
}


extern  instruction     *rMAKECALL( instruction *ins ) {
/*******************************************************
    turn an instruction into the approprate runtime call sequence, using
    the tables above to decide where parms go.
*/

    rtn_info            *info;
    label_handle        lbl;
    instruction         *left_ins;
    instruction         *new_ins;
    instruction         *la_ins;
    instruction         *last_ins;
    name                *reg_name;
    hw_reg_set          regs;
    hw_reg_set          all_regs;
    name                *temp;
    name                *also_used;
    conflict_node       *conf;
    hw_reg_set          tmp;
    type_class_def      parm2_class;

    if( !_IsConvert( ins ) ) {
        LookupRoutine( ins );
        CheckForPCS( ins );
    } else { /* RoutineNum might be wrong if we ran out of memory in ExpandIns*/
        RoutineNum = AskHow( ins->base_type_class, ins->type_class )
                   - BEG_RTNS;
    }
    FlipIns( ins );
    info = &RTInfo[  RoutineNum  ];
    regs = FirstReg( info->left );
    all_regs = regs;
    tmp = ReturnReg( WD, FALSE );
    HW_TurnOn( all_regs, tmp );
    left_ins = MakeMove( ins->operands[ 0 ], AllocRegName( regs ),
                          info->operand_class );
    ins->operands[ 0 ] = left_ins->result;
    MoveSegOp( ins, left_ins, 0 );
    PrefixIns( ins, left_ins );
    regs = FirstReg( info->right );
    also_used = NULL;
    if( !HW_CEqual( regs, HW_EMPTY ) ) {
        if( info->right == RL_8 ) {
            temp = ins->operands[ 1 ];
            if( temp->n.class==N_TEMP && ( temp->t.temp_flags & CONST_TEMP ) ) {
                temp = temp->v.symbol;
            }
            if( temp->n.class == N_CONSTANT ) {
                temp = Addressable( temp, info->operand_class );
                la_ins = MakeUnary( OP_CAREFUL_LA, temp,
                                      AllocRegName( HW_SI ), U2 );
                also_used = la_ins->operands[ 0 ];
                ins->operands[ 1 ] = la_ins->result;
                PrefixIns( ins, la_ins );
                if( !SegIsSS( temp ) ) {
                    new_ins = MakeMove( GetSegment( temp ),
                                        AllocRegName(HW_ES), U2 );
                    HW_CTurnOn( all_regs, HW_ES );
                    PrefixIns( ins, new_ins );
                    ++RoutineNum;
                }
            } else if( temp->n.class == N_TEMP ) {
                la_ins = MakeUnary( OP_CAREFUL_LA,temp,
                                    AllocRegName( HW_SI ),U2 );
                also_used = temp;
                ins->operands[ 1 ] = la_ins->result;
                MoveSegOp( ins, la_ins, 0 );
                DelSeg( la_ins );
                PrefixIns( ins, la_ins );
            } else if( ins->num_operands == 3 ) {
                new_ins = MakeMove( ins->operands[ 2 ],
                                    AllocRegName(HW_ES), U2 );
                ins->operands[ 2 ] = new_ins->result;
                PrefixIns( ins, new_ins );
                la_ins = MakeUnary( OP_CAREFUL_LA, temp,
                                    AllocRegName( HW_SI ), U2 );
                also_used = temp;
                ins->operands[ 1 ] = la_ins->result;
                MoveSegOp( ins, la_ins, 0 );
                DelSeg( la_ins );
                PrefixIns( ins, la_ins );
                HW_CTurnOn( all_regs, HW_ES );
                ++RoutineNum;
            } else if( ( temp->n.class == N_MEMORY && !SegIsSS( temp ) ) ||
                       ( temp->n.class == N_INDEXED && temp->i.base != NULL &&
                         !SegIsSS( temp->i.base ) ) ) {
                la_ins = MakeUnary( OP_CAREFUL_LA, ins->operands[ 1 ],
                                      AllocRegName( HW_ES_SI ), PT );
                also_used = ins->operands[ 1 ];
                ins->operands[ 1 ] = la_ins->result;
                PrefixIns( ins, la_ins );
                HW_CTurnOn( all_regs, HW_ES );
                ++RoutineNum;
            } else {
                la_ins = MakeUnary( OP_CAREFUL_LA, temp,
                                    AllocRegName( HW_SI ), U2 );
                also_used = temp;
                ins->operands[ 1 ] = la_ins->result;
                MoveSegOp( ins, la_ins, 0 );
                DelSeg( la_ins );
                PrefixIns( ins, la_ins );
            }
            HW_CTurnOn( all_regs, HW_SI );
        } else {
            /* If I knew how to turn a register list index into a type class,
               I'd do that, and avoid this if */
            if( info->right == RL_SI ) {
                new_ins = MakeMove( ins->operands[ 1 ], AllocRegName( regs ),
                                        U2 );
            } else {
                new_ins = MakeMove( ins->operands[ 1 ], AllocRegName( regs ),
                                        info->operand_class );
            }
            ins->operands[ 1 ] = new_ins->result;
            MoveSegOp( ins, new_ins, 0 );
            HW_TurnOn( all_regs, regs );
            PrefixIns( ins, new_ins );
        }
    } else if( NumOperands( ins ) == 2 ) {

⌨️ 快捷键说明

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