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 + -
显示快捷键?