docode.c

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

C
1,247
字号

static void MMModRM( int direction )
{
    D_Bit = direction;
    W_Bit = 0;
    DoOTModRM();
    CurrIns.modifier = MOD_NONE;

    if( CurrIns.op[ OP_1 ].mode == ADDR_REG ) {
        if( !(CurrIns.opcode == I_MOVD && direction == 0) ) {
            CurrIns.op[ OP_1 ].base += FIRST_MM_REG - FIRST_BYTE_REG;
        } else {
            CurrIns.op[ OP_1 ].base += FIRST_DWORD_REG - FIRST_BYTE_REG;
        }
    }
    if( CurrIns.op[ OP_2 ].mode == ADDR_REG ) {
        if( !(CurrIns.opcode == I_MOVD && direction == 1) ) {
            CurrIns.op[ OP_2 ].base += FIRST_MM_REG - FIRST_BYTE_REG;
        } else {
            CurrIns.op[ OP_2 ].base += FIRST_DWORD_REG - FIRST_BYTE_REG;
        }
    }
}


static  void    Opcode0F( char use_32 ) {
/***************************************/

    int                 index;
    unsigned char       second;

    GetDataByte();
    second = SecondByte;
    SecondByte = GetNextByte();
    W_Bit = second & 1;
    D_Bit = 0;
    switch( ( second >> 4 ) & 0x0F ) {
    case 0x00:
        index = _RegField( SecondByte );
        switch( second ) {
        case 0:
            CurrIns.opcode = S00Ops[ index ];
            GetOperands( OT_RMW, use_32 );
            CurrIns.mem_ref_size = 2;
            break;
        case 1:
            CurrIns.opcode = S01Ops[ index ];
            if( index == 7 ) {  // INVLPG
                GetOperands( OT_M, use_32 );
                CurrIns.modifier = MOD_NONE;
                CurrIns.mem_ref_size = 1;
            } else {
                GetOperands( OT_RMW, use_32 );
                if( index <= 3 ) {      // SIDT SGDT LGDT LIDT
                    CurrIns.mem_ref_size = 6;
                } else {
                    CurrIns.mem_ref_size = 2;
                }
            }
            break;
        case 2:
            CurrIns.opcode = I_LAR;
            GetOperands( OT_RV_RMW, use_32 );
            break;
        case 3:
            CurrIns.opcode = I_LSL;
            GetOperands( OT_RV_RMW, use_32 );
            break;
        case 6:
            CurrIns.opcode = I_CLTS;
            break;
        case 8:
            CurrIns.opcode = I_INVD;
            break;
        case 9:
            CurrIns.opcode = I_WBINVD;
            break;
        default:
            CurrIns.opcode = I_INVALID;
        }
        break;
    case 0x02:
        CurrIns.opcode = I_MOV;
        D_Bit = second & 2;
        GetOperands( S2xOpType[ second & 0x0f ], use_32 );
        break;
    case 0x03:
        switch( second & 0x0f ) {
        case 0x00:
            CurrIns.opcode = I_WRMSR;
            break;
        case 0x01:
            CurrIns.opcode = I_RDTSC;
            break;
        case 0x02:
            CurrIns.opcode = I_RDMSR;
            break;
        case 0x03:
            CurrIns.opcode = I_RDMPC;
            break;
        default:
            CurrIns.opcode = I_INVALID;
            break;
        }
        break;
    case 0x04:
        CurrIns.opcode = S4xInsTab[ second & 0x0f ].name;
        GetOperands( S4xInsTab[ second & 0x0f ].op_type, use_32 );
        break;
    case 0x08:
        CurrIns.opcode = S8xOps[ second & 0x0f ];
        GetOperands( OT_IP_INC16, use_32 );
        break;
    case 0x09:
        CurrIns.opcode = S9xOps[ second & 0x0f ];
        GetOperands( OT_RMB, use_32 );
        break;
    case 0x0A:
        CurrIns.opcode = SAxOps[ second & 0x0f ];
        if( CurrIns.opcode == I_IMUL ) {
            D_Bit = 1;
        }
        GetOperands( SAxOpType[ second & 0x0f ], use_32 );
        break;
    case 0x0B:
        CurrIns.opcode = SBxOps[ second & 0x0f ];
        if( CurrIns.opcode == I_BSF || CurrIns.opcode == I_BSR ) D_Bit = 1;
        if( CurrIns.opcode == I_BTx ) {
            W_Bit = 1;
            CurrIns.opcode = SBAOps[ _RegField( SecondByte ) ];
        }
        GetOperands( SBxOpType[ second & 0x0f ], use_32 );
        break;
    case 0x0C:
        if( second & 0x08 ) {
            CurrIns.opcode = I_BSWAP;
            CurrIns.num_oper = 1;
            CurrIns.op[ OP_1 ].mode = ADDR_REG;
            CurrIns.op[ OP_1 ].base = VarReg( FIRST_WORD_REG + ( second & 7 ) );
        } else if( (second & 0x0f) == 0x07 ) {
            /* group 9 */
            if( (SecondByte & 0x38) == 0x08 ) {
                CurrIns.opcode = I_CMPXCHG8B;
                CurrIns.num_oper = 1;
                ModRMOp( OP_1, FALSE );
            } else {
                CurrIns.opcode = I_INVALID;
            }
        } else {
            CurrIns.opcode = SCxOps[ second & 0x07 ];
            GetOperands( SCxOpType[ second & 0x07 ], use_32 );
        }
        break;
    case 0x06:
        CurrIns.opcode = S6xInsTab[ second & 0x0f ].name;
        GetOperands( S6xInsTab[ second & 0x0f ].op_type, use_32 );
        break;
    case 0x07:
        CurrIns.opcode = S7xInsTab[ second & 0x0f ].name;
        switch( second & 0x0f ) {
        case 0x1:
        case 0x2:
        case 0x3:
            /* a shift immediate opcode */
            switch( SecondByte & 0xf8 ) {
            case 0xF0: /* PSLL */
                break;
            case 0xD0: /* PSRL */
                CurrIns.opcode += 1;
                break;
            case 0xE0: /* PSRA */
                CurrIns.opcode += 2;
                if( CurrIns.opcode == I_PSRAQ ) {
                    /* doesn't exist */
                    CurrIns.opcode = I_INVALID;
                    return;
                }
                break;
            default:
                CurrIns.opcode = I_INVALID;
                return;
            }
            GetDataByte(); /* get set up for grabbing the immediate */
        }
        GetOperands( S7xInsTab[ second & 0x0f ].op_type, use_32 );
        break;
    case 0x0d:
        CurrIns.opcode = SDxInsTab[ second & 0x0f ].name;
        GetOperands( SDxInsTab[ second & 0x0f ].op_type, use_32 );
        break;
    case 0x0e:
        CurrIns.opcode = SExInsTab[ second & 0x0f ].name;
        GetOperands( SExInsTab[ second & 0x0f ].op_type, use_32 );
        break;
    case 0x0f:
        CurrIns.opcode = SFxInsTab[ second & 0x0f ].name;
        GetOperands( SFxInsTab[ second & 0x0f ].op_type, use_32 );
        break;
    default:
        CurrIns.opcode = I_INVALID;
        break;
    }
}


static  void  ConstByteOp( int op )
/*********************************/

{
    operand     *opnd;

    opnd = &CurrIns.op[ op ];
    opnd->mode = ADDR_CONST;
    opnd->size = 1;
    opnd->offset = InsOffset();
    opnd->disp = GetDataByte();
}


static void ConstSexOp( int op )
/******************************/

{
    ConstByteOp( op );
    CurrIns.op[ op ].size = ( CurrIns.pref & OPND_LONG ) ? 4 : 2;
}


static  void  ConstWordOp( int op )
/*********************************/

{
    operand     *opnd;

    opnd = &CurrIns.op[ op ];
    opnd->mode = ADDR_CONST;
    opnd->size = 2;
    opnd->offset = InsOffset();
    opnd->disp = GetDataWord();
}


static  void  ConstLongOp( int op )
/*********************************/

{
    operand     *opnd;

    opnd = &CurrIns.op[ op ];
    opnd->mode = ADDR_CONST;
    opnd->size = 4;
    opnd->offset = InsOffset();
    opnd->disp = GetDataLong();
}


static  void  ConstVarOp( int op )
/*********************************/

{
    if( CurrIns.pref & OPND_LONG ) {
        ConstLongOp( op );
    } else {
        ConstWordOp( op );
    }
}


static  void  AccumOp( int op )
/*****************************/

{
    CurrIns.op[ op ].mode = ADDR_REG;
    if( W_Bit ) {
        CurrIns.op[ op ].base = VarReg( AX_REG );
    } else {
        CurrIns.op[ op ].base = AL_REG;
    }
}


static  void  GetOperands( operand_type op_type, char use_32 )
#define _FixDisp( x ) ( use_32 ? (x) : (x) & 0xFFFF )
/************************************************************/
{
    int                 op1;
    int                 op2;
    int                 reg;
    uint_32             disp;
    address_mode        mode;
    prefix              save_pref;

    op1 = OP_1;
    op2 = OP_2;
    switch( op_type ) {
    case OT_NULL:
        break;
    case OT_ES_DI:              /* stos, scas */
        if( CurrIns.seg_used == NULL_REG ) {
            CurrIns.seg_used = ES_REG;
        }
        /* fall through */
    case OT_DS_SI:              /* lods */
    case OT_DS_SI_ES_DI:        /* movs */
        CurrIns.mem_ref_op = OP_1;
        mode = ADDR_DS_SI + ( op_type - OT_DS_SI );
        if( CurrIns.pref & ADDR_LONG ) ++mode;  /* DS_SI -> DS_ESI */
        CurrIns.op[ OP_1 ].mode = mode;
        break;
    case OT_THREE:              /* int 3 */
        CurrIns.num_oper = 1;
        CurrIns.op[ OP_1 ].mode = ADDR_CONST;
        CurrIns.op[ OP_1 ].disp = 3;
        break;
    case OT_ENTER:              /* enter locals,level */
        CurrIns.num_oper = 2;
        ConstWordOp( OP_1 );
        ConstByteOp( OP_2 );
        break;
    case OT_DX_ACCUM:           /* out DX,AL */
        op1 = OP_2;
        op2 = OP_1;
        /* fall through */
    case OT_ACCUM_DX:           /* in AL,DX */
        CurrIns.num_oper = 2;
        AccumOp( op1 );
        CurrIns.op[ op2 ].mode = ADDR_REG;
        CurrIns.op[ op2 ].base = DX_REG;
        break;
    case OT_IMMED8_ACCUM:       /* out 10,AX */
        op1 = OP_2;
        op2 = OP_1;
        /* fall through */
    case OT_ACCUM_IMMED8:       /* in AL,10 */
        CurrIns.num_oper = 2;
        AccumOp( op1 );
        ConstByteOp( op2 );
        break;
    case OT_ACCUM_IMMED:        /* mov AL,7 */
        CurrIns.num_oper = 2;
        AccumOp( OP_1 );
        if( W_Bit ) {
            ConstVarOp( OP_2 );
        } else {
            ConstByteOp( OP_2 );
        }
        break;
    case OT_ACCUM_MEM:          /* mov AX,[a000] */
        if( D_Bit ) {
            op1 = OP_2;
            op2 = OP_1;
        }
        CurrIns.num_oper = 2;
        AccumOp( op1 );
        CurrIns.mem_ref_op = op2;
        if( CurrIns.pref & ADDR_LONG ) {
            ConstLongOp( op2 );
        } else {
            ConstWordOp( op2 );
        }
        CurrIns.op[ op2 ].mode = ADDR_ABS;
#if defined( O2A )
        if( Options & FORM_ASSEMBLER ) {
            if( W_Bit == 0 ) {
                CurrIns.modifier = MOD_BYTE;
            } else if( CurrIns.pref & OPND_LONG ) {
                CurrIns.modifier = MOD_LINT;
            } else {
                CurrIns.modifier = MOD_WORD;
            }
        }
#endif
        break;
    case OT_ACCUM_REG16:        /* xchg AX,CX */
        CurrIns.num_oper = 2;
        CurrIns.op[ OP_1 ].mode = ADDR_REG;
        CurrIns.op[ OP_1 ].base = VarReg( AX_REG );
        CurrIns.op[ OP_2 ].mode = ADDR_REG;
        CurrIns.op[ OP_2 ].base = VarReg( FIRST_WORD_REG + ( Opcode & 7 ) );
        break;
    case OT_ESC:                /* float instructions */
        GetFppOp();
        break;
    case OT_IMMED:              /* push $12 */
        CurrIns.num_oper = 1;
        ConstSexOp( OP_1 );
        break;
    case OT_IMMED8:             /* int $21 */
        CurrIns.num_oper = 1;
        ConstByteOp( OP_1 );
        break;
    case OT_IMMED_WORD:         /* ret 2 */
        CurrIns.num_oper = 1;
        ConstWordOp( OP_1 );
        break;
    case OT_IMMED16:            /* ret 2 */
        CurrIns.num_oper = 1;
        ConstVarOp( OP_1 );
        break;
    case OT_IP_INC8:            /* je L1 */
    case OT_IP_INC16:           /* call/jmp L2 */
        CurrIns.num_oper = 1;
        CurrIns.op[ OP_1 ].mode = ADDR_LABEL;
        CurrIns.op[ OP_1 ].offset = InsOffset();
        if( op_type == OT_IP_INC8 ) {
            CurrIns.op[ OP_1 ].size = 1;
            disp = GetDataByte();
        } else if ( CurrIns.pref & OPND_LONG ) {
            CurrIns.op[ OP_1 ].size = 4;
            disp = GetDataLong();
        } else {
            CurrIns.op[ OP_1 ].size = 2;
            disp = GetDataWord();
        }
        disp += GetOffset();
        CurrIns.op[ OP_1 ].disp = _FixDisp( disp );

⌨️ 快捷键说明

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