asmjump.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 738 行 · 第 1/2 页
C
738 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: CALL/JMP processing
*
****************************************************************************/
#include "asmglob.h"
#include "asmins.h"
#include "asmdefs.h"
#include "asmfixup.h"
#include "asmeval.h"
#if defined( _STANDALONE_ )
#include "directiv.h"
#include "asminput.h"
#endif
/* prototypes */
int ptr_operator( memtype mem_type, uint_8 fix_mem_type );
int jmp( expr_list *opndx );
#if defined( _STANDALONE_ )
extern void GetInsString( enum asm_token, char *, int );
extern int SymIs32( struct asm_sym *sym );
extern void check_assume( struct asm_sym *sym, enum prefix_reg default_reg );
extern void find_frame( struct asm_sym *sym );
static enum asm_token getJumpNegation( enum asm_token instruction )
/*****************************************************************/
{
switch( instruction ) {
case T_JA: return( T_JNA );
case T_JAE: return( T_JNAE );
case T_JB: return( T_JNB );
case T_JBE: return( T_JNBE );
case T_JC: return( T_JNC );
case T_JE: return( T_JNE );
case T_JG: return( T_JNG );
case T_JGE: return( T_JNGE );
case T_JL: return( T_JNL );
case T_JLE: return( T_JNLE );
case T_JNA: return( T_JA );
case T_JNAE: return( T_JAE );
case T_JNB: return( T_JB );
case T_JNBE: return( T_JBE );
case T_JNC: return( T_JC );
case T_JNE: return( T_JE );
case T_JNG: return( T_JG );
case T_JNGE: return( T_JGE );
case T_JNL: return( T_JL );
case T_JNLE: return( T_JLE );
case T_JNO: return( T_JO );
case T_JNP: return( T_JP );
case T_JNS: return( T_JS );
case T_JNZ: return( T_JZ );
case T_JO: return( T_JNO );
case T_JP: return( T_JNP );
case T_JPE: return( T_JPO );
case T_JPO: return( T_JPE );
case T_JS: return( T_JNS );
case T_JZ: return( T_JNZ );
default:
return( (enum asm_token)ERROR );
}
}
static void jumpExtend( int far_flag )
/*************************************/
{
unsigned i;
unsigned next_ins_size;
enum asm_token negation;
char buffer[MAX_LINE_LEN];
/* there MUST be a conditional jump instruction in asmbuffer */
for( i = 0; ; i++ ) {
if( ( AsmBuffer[i]->token == T_INSTR )
&& IS_JMP( AsmBuffer[i]->value ) ) {
break;
}
}
AsmWarn( 4, EXTENDING_JUMP );
negation = getJumpNegation( AsmBuffer[i]->value );
GetInsString( negation, buffer, MAX_LINE_LEN );
if( far_flag ) {
next_ins_size = Code->use32 ? 7 : 5;
} else {
next_ins_size = Code->use32 ? 5 : 3;
}
sprintf( buffer + strlen( buffer ), " SHORT $+%d ", next_ins_size+2 );
InputQueueLine( buffer );
if( far_flag ) {
strcpy( buffer, "jmpf " );
} else {
strcpy( buffer, "jmp " );
}
for( i++; AsmBuffer[i]->token != T_FINAL; i++ ) {
switch( AsmBuffer[i]->token ) {
case T_NUM:
case T_DEC_NUM:
case T_OCT_NUM:
case T_HEX_NUM_0:
case T_HEX_NUM:
case T_BIN_NUM:
itoa( AsmBuffer[i]->value, buffer+strlen( buffer ), 10 );
break;
case T_OP_SQ_BRACKET:
strcat( buffer, "[" );
break;
case T_CL_SQ_BRACKET:
strcat( buffer, "]" );
break;
default:
strcat( buffer, AsmBuffer[i]->string_ptr );
break;
}
}
InputQueueLine( buffer );
return;
}
static void FarCallToNear( void )
/*******************************/
{
unsigned i;
char buffer[MAX_LINE_LEN];
/* there MUST be a call instruction in asmbuffer */
for( i = 0; ; i++ ) {
if( ( AsmBuffer[i]->token == T_INSTR )
&& ( AsmBuffer[i]->value == T_CALL ) ) {
break;
}
}
if( Parse_Pass == PASS_2 )
AsmWarn( 4, CALL_FAR_TO_NEAR );
InputQueueLine( "PUSH CS" );
strcpy( buffer, "CALL NEAR PTR " );
for( i++; AsmBuffer[i]->token != T_FINAL; i++ ) {
switch( AsmBuffer[i]->token ) {
case T_NUM:
case T_DEC_NUM:
case T_OCT_NUM:
case T_HEX_NUM_0:
case T_HEX_NUM:
case T_BIN_NUM:
itoa( AsmBuffer[i]->value, buffer+strlen( buffer ), 10 );
break;
case T_OP_SQ_BRACKET:
strcat( buffer, "[" );
break;
case T_CL_SQ_BRACKET:
strcat( buffer, "]" );
break;
default:
strcat( buffer, AsmBuffer[i]->string_ptr );
break;
}
}
InputQueueLine( buffer );
return;
}
#endif
int jmp( expr_list *opndx )
/*
determine the displacement of jmp;
*/
{
int_32 addr;
enum fixup_types fixup_type;
enum fixup_options fixup_option;
enum sym_state state;
struct asm_sym *sym;
#if defined( _STANDALONE_ )
dir_node *seg;
#endif
Code->data[Opnd_Count] = opndx->value;
sym = opndx->sym;
if( sym == NULL ) {
if( IS_JMPCALLN( Code->info.token ) )
Code->info.token++;
if( Code->data[Opnd_Count] > USHRT_MAX )
Code->info.opnd_type[Opnd_Count] = OP_I32;
else
Code->info.opnd_type[Opnd_Count] = OP_I16;
return( NOT_ERROR );
}
#if defined( _STANDALONE_ )
if( sym->mem_type == MT_ERROR ) {
AsmError( LABEL_NOT_DEFINED );
return( ERROR );
}
#endif
state = sym->state;
#if defined( _STANDALONE_ )
seg = GetSeg( sym );
if( seg == NULL || CurrSeg == NULL || CurrSeg->seg != seg ) {
/* jumps to another segment are just like to another file */
state = SYM_EXTERNAL;
}
#endif
if( !Code->mem_type_fixed ) {
Code->mem_type = MT_EMPTY;
}
fixup_option = OPTJ_NONE;
fixup_type = FIX_RELOFF8;
switch( state ) {
case SYM_INTERNAL:
#if defined( _STANDALONE_ )
case SYM_PROC:
#endif
if( ( Code->mem_type == MT_EMPTY || Code->mem_type == MT_SHORT
|| Code->mem_type == MT_NEAR )
&& sym->mem_type != MT_WORD
&& sym->mem_type != MT_DWORD
&& sym->mem_type != MT_FWORD
&& !IS_JMPCALLF( Code->info.token ) ) {
#if defined( _STANDALONE_ )
if( ( Code->info.token == T_CALL )
&& ( Code->mem_type == MT_EMPTY )
&& ( sym->mem_type == MT_FAR ) ) {
FarCallToNear();
return( SCRAP_INSTRUCTION );
}
addr = sym->offset;
#else
addr = sym->addr;
#endif
addr -= ( AsmCodeAddress + 2 ); // calculate the displacement
addr += Code->data[Opnd_Count];
switch( Code->info.token ) {
case T_JCXZ:
case T_LOOPW:
case T_LOOPEW:
case T_LOOPZW:
case T_LOOPNEW:
case T_LOOPNZW:
if( Code->use32 ) {
// 1 extra byte for OPNSIZ
addr--;
}
break;
case T_JECXZ:
case T_LOOPD:
case T_LOOPED:
case T_LOOPZD:
case T_LOOPNED:
case T_LOOPNZD:
if( !Code->use32 ) {
// 1 extra byte for OPNSIZ
addr--;
}
break;
}
if( Code->info.token == T_CALL && Code->mem_type == MT_EMPTY ) {
Code->mem_type = MT_NEAR;
}
if( Code->mem_type != MT_NEAR && Code->info.token != T_CALL
&& ( addr >= SCHAR_MIN && addr <= SCHAR_MAX ) ) {
Code->info.opnd_type[Opnd_Count] = OP_I8;
} else {
/* near jmp */
if( Code->use32 ) {
Code->info.opnd_type[Opnd_Count] = OP_I32;
addr -= 3; // 32 bit displacement
} else {
Code->info.opnd_type[Opnd_Count] = OP_I16;
addr -= 1; // 16 bit displacement
}
if( IS_JMP( Code->info.token ) ) {
switch( Code->info.token ) {
case T_JMP:
case T_JMPF:
case T_JCXZ:
case T_JECXZ:
break;
default:
// 1 extra byte for opcode ( 0F )
addr--;
break;
}
}
}
/* store the displacement */
Code->data[Opnd_Count] = addr;
switch( Code->info.token ) {
case T_JCXZ:
case T_JECXZ:
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 defined( _STANDALONE_ )
#define GOOD_PHASE !PhaseError &&
#else
#define GOOD_PHASE
#endif
if( GOOD_PHASE (Code->info.opnd_type[Opnd_Count] != OP_I8) ) {
AsmError( JUMP_OUT_OF_RANGE );
return( ERROR );
}
Code->info.opnd_type[Opnd_Count] = OP_I8;
break;
}
if( (Code->info.cpu&P_CPU_MASK) < P_386 && IS_JMP( Code->info.token ) ) {
/* look into jump extension */
switch( Code->info.token ) {
case T_JMP:
case T_JMPF:
break;
default:
if( Code->info.opnd_type[Opnd_Count] != OP_I8 ) {
#if defined( _STANDALONE_ )
if( Code->mem_type == MT_EMPTY ) {
jumpExtend( 0 );
return( SCRAP_INSTRUCTION );
} else if( !PhaseError ) {
AsmError( JUMP_OUT_OF_RANGE );
return( ERROR );
}
#else
AsmError( JUMP_OUT_OF_RANGE );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?