asmjump.c

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

C
738
字号
                        return( ERROR );
#endif
                    }
                }
            }
            break;
        }
        /* otherwise fall through & get handled like external symbols */
    case SYM_UNDEFINED:
    case SYM_EXTERNAL:

        /* forward ref, or external symbol */
        if( Code->mem_type == MT_EMPTY && sym->mem_type != MT_EMPTY ) {
            switch( sym->mem_type ) {
            case MT_FAR:
                if( IS_JMPCALLN( Code->info.token ) ) {
                    Code->info.token++;
                }
                // fall through
            case MT_SHORT:
            case MT_NEAR:
                Code->mem_type = sym->mem_type;
                break;
#if defined( _STANDALONE_ )
            case MT_PROC:
                Code->mem_type = IS_PROC_FAR() ? MT_FAR : MT_NEAR;
                if( IS_JMPCALLN( Code->info.token )
                    && ( Code->mem_type == MT_FAR ) ) {
                    Code->info.token++;
                }
                break;
#endif
            case MT_FWORD:
                if( ptr_operator( MT_FWORD, TRUE ) == ERROR )
                    return( ERROR );
                break;
            default:
                Code->mem_type = sym->mem_type;
            }
        }
        if( ( Code->mem_type == MT_FAR ) && IS_JMPCALLN( Code->info.token ) ) {
            Code->info.token++;
        }
        switch( Code->info.token ) {
        case T_CALLF:
        case T_JMPF:
            switch( Code->mem_type ) {
            case MT_SHORT:
            case MT_NEAR:
                if( Opnd_Count == OPND1 && Code->mem_type_fixed ) {
                    AsmError( CANNOT_USE_SHORT_OR_NEAR );
                    return( ERROR );
                }
                /* fall through */
            case MT_FAR:
            case MT_EMPTY:
#if defined( _STANDALONE_ )
                SET_OPSIZ( Code, SymIs32( sym ));
                find_frame( sym );
#endif
                if( Opnd_Count == OPND2 ) {
                    if( oper_32( Code ) ) {
                        fixup_type = FIX_OFF32;
                        Code->info.opnd_type[Opnd_Count] = OP_I32;
                    } else {
                        fixup_type = FIX_OFF16;
                        Code->info.opnd_type[Opnd_Count] = OP_I16;
                    }
                } else {
                    if( oper_32( Code ) ) {
                        fixup_type = FIX_PTR32;
                        Code->info.opnd_type[Opnd_Count] = OP_J48;
                    } else {
                        fixup_type = FIX_PTR16;
                        Code->info.opnd_type[Opnd_Count] = OP_J32;
                    }
                }
                break;
            case MT_BYTE:
            case MT_WORD:
#if defined( _STANDALONE_ )
            case MT_SBYTE:
            case MT_SWORD:
#endif
                AsmError( INVALID_SIZE );
                return( ERROR );
            case MT_DWORD:
            case MT_FWORD:
#if defined( _STANDALONE_ )
            case MT_SDWORD:
#endif
                return( INDIRECT_JUMP );
            case MT_QWORD:
            case MT_TBYTE:
            case MT_OWORD:
                AsmError( INVALID_SIZE );
                return( ERROR );
            }
            break;
        case T_CALL:
            if( Code->mem_type == MT_SHORT ) {
                AsmError( CANNOT_USE_SHORT_WITH_CALL );
                return( ERROR );
            } else if( Code->mem_type == MT_EMPTY ) {
#if defined( _STANDALONE_ )
                fixup_option = OPTJ_CALL;
#else
                fixup_option = OPTJ_NONE;
#endif
                if( Code->use32 ) {
                    fixup_type = FIX_RELOFF32;
                    Code->info.opnd_type[Opnd_Count] = OP_I32;
                } else {
                    fixup_type = FIX_RELOFF16;
                    Code->info.opnd_type[Opnd_Count] = OP_I16;
                }
                break;
            }
            /* fall through */
        case T_JMP:
            switch( Code->mem_type ) {
            case MT_SHORT:
                fixup_option = OPTJ_EXPLICIT;
                fixup_type = FIX_RELOFF8;
                Code->info.opnd_type[Opnd_Count] = OP_I8;
                break;
            case MT_FAR:
                AsmError( SYNTAX_ERROR );
                break;
            case MT_EMPTY:
                // forward reference
                // inline assembler jmp default distance is near
                // stand-alone assembler jmp default distance is short
                fixup_option = OPTJ_NONE;
#if defined( _STANDALONE_ )
                /* guess short if JMP, we will expand later if needed */
                fixup_type = FIX_RELOFF8;
                Code->info.opnd_type[Opnd_Count] = OP_I8;
#else
                if( Code->use32 ) {
                    fixup_type = FIX_RELOFF32;
                    Code->info.opnd_type[Opnd_Count] = OP_I32;
                } else {
                    fixup_type = FIX_RELOFF16;
                    Code->info.opnd_type[Opnd_Count] = OP_I16;
                }
#endif
                break;
            case MT_NEAR:
                fixup_option = OPTJ_EXPLICIT;
                if( Code->use32 ) {
                    fixup_type = FIX_RELOFF32;
                    Code->info.opnd_type[Opnd_Count] = OP_I32;
                } else {
                    fixup_type = FIX_RELOFF16;
                    Code->info.opnd_type[Opnd_Count] = OP_I16;
                }
                break;
            case MT_DWORD:
            case MT_WORD:
#if defined( _STANDALONE_ )
            case MT_SDWORD:
            case MT_SWORD:
#endif
                return( INDIRECT_JUMP );
#if defined( _STANDALONE_ )
            case MT_SBYTE:
#endif
            case MT_BYTE:
            case MT_FWORD:
            case MT_QWORD:
            case MT_TBYTE:
            case MT_OWORD:
                AsmError( INVALID_SIZE );
                return( ERROR );
            }
//            check_assume( sym, EMPTY );
            break;
        case T_JCXZ:
        case T_JECXZ:
            // JCXZ and JECXZ always require SHORT label
        case T_LOOP:
        case T_LOOPE:
        case T_LOOPNE:
        case T_LOOPNZ:
        case T_LOOPZ:
        case T_LOOPD:
        case T_LOOPED:
        case T_LOOPNED:
        case T_LOOPNZD:
        case T_LOOPZD:
        case T_LOOPW:
        case T_LOOPEW:
        case T_LOOPNEW:
        case T_LOOPNZW:
        case T_LOOPZW:
            if( Code->mem_type != MT_EMPTY && Code->mem_type != MT_SHORT ) {
                AsmError( ONLY_SHORT_DISPLACEMENT_IS_ALLOWED );
                return( ERROR );
            }
            Code->info.opnd_type[Opnd_Count] = OP_I8;
            fixup_option = OPTJ_EXPLICIT;
            fixup_type = FIX_RELOFF8;
            break;
        default:
            if( (Code->info.cpu&P_CPU_MASK) >= P_386 ) {
                switch( Code->mem_type ) {
                case MT_SHORT:
                    fixup_option = OPTJ_EXPLICIT;
                    fixup_type = FIX_RELOFF8;
                    Code->info.opnd_type[Opnd_Count] = OP_I8;
                    break;
                case MT_EMPTY:
                    // forward reference
                    // inline assembler default distance is near
                    // stand-alone assembler default distance is short
#if defined( _STANDALONE_ )
                    fixup_option = OPTJ_JXX;
                    fixup_type = FIX_RELOFF8;
                    Code->info.opnd_type[Opnd_Count] = OP_I8;
                    break;
#endif
                case MT_NEAR:
                    fixup_option = OPTJ_EXPLICIT;
                    if( Code->use32 ) {
                        fixup_type = FIX_RELOFF32;
                        Code->info.opnd_type[Opnd_Count] = OP_I32;
                    } else {
                        fixup_type = FIX_RELOFF16;
                        Code->info.opnd_type[Opnd_Count] = OP_I16;
                    }
                    break;
                case MT_FAR:
#if defined( _STANDALONE_ )
                    jumpExtend( 1 );
                    return( SCRAP_INSTRUCTION );
#endif
                default:
                    AsmError( ONLY_SHORT_AND_NEAR_DISPLACEMENT_IS_ALLOWED );
                    return( ERROR );
                }
            } else {
                // the only mode in 8086, 80186, 80286 is
                // Jxx SHORT
                switch( Code->mem_type ) {
                case MT_EMPTY:
#if defined( _STANDALONE_ )
                    fixup_option = OPTJ_EXTEND;
                    fixup_type = FIX_RELOFF8;
                    Code->info.opnd_type[Opnd_Count] = OP_I8;
                    break;
#endif
                case MT_SHORT:
                    fixup_option = OPTJ_EXPLICIT;
                    fixup_type = FIX_RELOFF8;
                    Code->info.opnd_type[Opnd_Count] = OP_I8;
                    break;
                default:
                    AsmError( ONLY_SHORT_DISPLACEMENT_IS_ALLOWED );
                    return( ERROR );
                }
            }
        }
        AddFixup( sym, fixup_type, fixup_option );
        break;
    default: /* SYM_STACK */
        AsmError( NO_JUMP_TO_AUTO );
        return( ERROR );
    }
    return( NOT_ERROR );
}

int ptr_operator( memtype mem_type, uint_8 fix_mem_type )
/***********************************************/
/*
  determine what should be done with SHORT, NEAR, FAR, BYTE, WORD, DWORD, PTR
  operator;
*/
{
    /* new idea:
     * when we get a near/far/dword/etc, just set distance / mem_type
     * operator will be called again with PTR, then we set the opsiz, etc.
     */

    if( Code->info.token == T_LEA )
        return( NOT_ERROR );
    if( Code->info.token == T_SMSW )
        return( NOT_ERROR );
    if( mem_type == MT_PTR ) {
        /* finish deciding what type to make the inst NOW
         * ie: decide size overrides etc.
         */
        if( Code->use32 && MEM_TYPE( Code->mem_type, WORD ) ) {
            // if we are in use32 mode, we have to add OPSIZ prefix for
            // most of the 386 instructions ( except MOVSX and MOVZX )
            // when we find WORD PTR

            if( !IS_BRANCH( Code->info.token ) ) {
                if( Code->info.opnd_type[OPND1] == OP_MMX ) {
                /* JBS 2001/02/19
                no WORD operands for MMX instructions, only 64-bit or 128-bit
                so no WORD override needed
                    */
                } else {
                    switch( Code->info.token ) {
                    case T_MOVSX:
                    case T_MOVZX:
                        break;
                    default:
                        Code->prefix.opsiz = TRUE;
                        break;
                    }
                }
            }

        } else if( !Code->use32 && MEM_TYPE( Code->mem_type, DWORD ) ) {

            /* if we are not in use32 mode, we have to add OPSIZ
             * when we find DWORD PTR
             * unless we have a LXS ins.
             * which moves a DWORD ptr into SR:word reg
             * fixme  - can this be done by breaking up the LXS instructions in
             *          asmins.h, and then putting F_32 or F_16 to append
             *      opsize bytes when necessary ?
             */
            if( !IS_BRANCH( Code->info.token ) ) {

                if( Code->info.opnd_type[OPND1] == OP_MMX ) {
                    /* JBS 2001/02/19
                       no WORD operands for MMX instructions, only 64-bit or 128-bit
                       so no DWORD override needed
                     */
                } else {
                    switch( Code->info.token ) {
                    case T_LDS:
                    case T_LES:
                    case T_LFS:
                    case T_LGS:
                    case T_LSS:
                        /* in these cases, opsize does NOT need to be changed  */
                        break;
                    default:
                        // OPSIZ prefix
                        Code->prefix.opsiz = TRUE;
                    }
                }
            }
        }
    } else {
        if( ( mem_type != MT_EMPTY ) && ( Code->mem_type_fixed == FALSE ) ) {
#if defined( _STANDALONE_ )
            if( mem_type != MT_STRUCT ) {
#endif
                Code->mem_type = mem_type;
                if( fix_mem_type ) {
                    Code->mem_type_fixed = TRUE;
                    if( IS_JMPCALLN( Code->info.token ) && ( mem_type == MT_FAR ) ) {
                        Code->info.token++;
                    }
                }

#if defined( _STANDALONE_ )
            }
#endif
        }
    }
    return( NOT_ERROR );
}

⌨️ 快捷键说明

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