asmins.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,095 行 · 第 1/5 页
C
2,095 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
/* set this macro to 0 if you do NOT want to allow structures to be defined
* ie:
* struct foo
* ...
* foo ends
* ...
* bar foo < 4, 2, 3 >
*/
#define ALLOW_STRUCT_INIT 1
#include "asmglob.h"
#include "asminsd.h"
#include "asmdefs.h"
#include "asmexpnd.h"
#include "asmfixup.h"
#include "asmeval.h"
#include "asmlabel.h"
#if defined( _STANDALONE_ )
#include "directiv.h"
#include "myassert.h"
#include "asminput.h"
#endif
extern int match_phase_1( void );
extern int ptr_operator( memtype, uint_8 );
extern int jmp( expr_list * );
static struct asm_code Code_Info;
struct asm_code *Code = &Code_Info;
unsigned char Opnd_Count;
static void SizeString( unsigned op_size );
static int check_size( void );
static int segm_override_jumps( expr_list *opndx );
#if defined( _STANDALONE_ )
extern int directive( int , long );
extern int SymIs32( struct asm_sym *sym );
static void check_assume( struct asm_sym *, enum prefix_reg );
extern int_8 DefineProc; // TRUE if the definition of procedure
// has not ended
uint_8 CheckSeg; // if checking of opened segment is needed
int_8 Frame; // Frame of current fixup
uint_8 Frame_Datum; // Frame datum of current fixup
struct asm_sym *SegOverride;
static int in_epilogue = 0;
#else
#define directive( i, value ) cpu_directive( value )
#endif
extern void make_inst_hash_table( void );
static int curr_ptr_type;
static char ConstantOnly;
static int mem2code( char, int, int, asm_sym * );
/* moved here from asmline */
static struct asm_tok tokens[MAX_TOKEN];
struct asm_tok *AsmBuffer[MAX_TOKEN]; // buffer to store token
#if defined( _STANDALONE_ )
void find_frame( struct asm_sym *sym )
/*******************************************/
{
if( SegOverride != NULL ) {
sym = SegOverride;
if( sym->state == SYM_GRP ) {
Frame = FRAME_GRP;
Frame_Datum = GetGrpIdx( sym );
} else if( sym->segment != NULL ) {
Frame = FRAME_SEG;
Frame_Datum = GetSegIdx( sym->segment );
}
} else {
switch( sym->state ) {
case SYM_INTERNAL:
case SYM_PROC:
if( sym->segment != NULL ) {
if( GetGrp( sym ) != NULL ) {
Frame = FRAME_GRP;
Frame_Datum = GetGrpIdx( GetGrp( sym ) );
} else {
Frame = FRAME_SEG;
Frame_Datum = GetSegIdx( sym->segment );
}
}
break;
case SYM_GRP:
Frame = FRAME_GRP;
Frame_Datum = GetGrpIdx( sym );
break;
case SYM_SEG:
Frame = FRAME_SEG;
Frame_Datum = GetSegIdx( sym->segment );
break;
default:
break;
}
}
}
#endif
static int comp_mem( int reg1, int reg2 )
/***************************************/
/*
- compare and return the r/m field encoding of 16-bit address mode;
- call by mem2code() only;
*/
{
switch( reg1 ) {
case T_BX:
switch( reg2 ) {
case T_SI: return( MEM_BX_SI );
case T_DI: return( MEM_BX_DI );
}
break;
case T_BP:
switch( reg2 ) {
case T_SI: return( MEM_BP_SI );
case T_DI: return( MEM_BP_DI );
}
break;
}
AsmError( INVALID_MEMORY_POINTER );
return( ERROR );
}
static void seg_override( int seg_reg, asm_sym *sym )
/***************************************************/
/*
- determine if segment override is necessary with the current address mode;
*/
{
enum prefix_reg default_seg;
#if defined( _STANDALONE_ )
enum assume_reg assume_seg;
switch( seg_reg ) {
case T_SS:
case T_BP:
case T_EBP:
case T_ESP:
default_seg = PREFIX_SS;
break;
default:
default_seg = PREFIX_DS;
}
if( sym != NULL ) {
if( Code->prefix.seg == EMPTY ) {
if( Code->info.token == T_LEA ) {
check_assume( sym, EMPTY );
} else {
check_assume( sym, default_seg );
}
} else {
switch( Code->prefix.seg ) {
case PREFIX_ES:
assume_seg = ASSUME_ES;
break;
case PREFIX_CS:
assume_seg = ASSUME_CS;
break;
case PREFIX_SS:
assume_seg = ASSUME_SS;
break;
case PREFIX_DS:
assume_seg = ASSUME_DS;
break;
case PREFIX_FS:
assume_seg = ASSUME_FS;
break;
case PREFIX_GS:
assume_seg = ASSUME_GS;
break;
default:
break;
}
if( GetPrefixAssume( sym, assume_seg ) == ASSUME_NOTHING ) {
// AsmWarn( 3, CANNOT_ADDRESS_WITH_ASSUMED_REGISTER );
}
}
}
if( Code->prefix.seg == default_seg ) {
Code->prefix.seg = EMPTY;
}
#else
if( Code->prefix.seg != EMPTY ) {
switch( seg_reg ) {
case T_SS:
case T_BP:
case T_EBP:
case T_ESP:
default_seg = PREFIX_SS;
break;
default:
default_seg = PREFIX_DS;
}
if( Code->prefix.seg == default_seg ) {
Code->prefix.seg = EMPTY;
}
}
#endif
}
#if defined( _STANDALONE_ )
static void check_assume( struct asm_sym *sym, enum prefix_reg default_reg )
/**************************************************************************/
/* Check if an assumed register is found, and prefix a register if necessary */
{
enum assume_reg reg;
enum assume_reg def_reg;
/**/myassert( sym != NULL );
if( sym->state == SYM_UNDEFINED )
return;
switch( default_reg ) {
case PREFIX_SS:
def_reg = ASSUME_SS;
break;
case PREFIX_DS:
def_reg = ASSUME_DS;
break;
default:
def_reg = ASSUME_NOTHING;
break;
}
reg = GetAssume( sym, def_reg );
if( reg == ASSUME_NOTHING ) {
if( ( sym->state != SYM_EXTERNAL ) && ( sym->state != SYM_PROC ) ) {
if( Parse_Pass == PASS_2 ) {
AsmWarn( 3, CANNOT_ADDRESS_WITH_ASSUMED_REGISTER );
}
} else {
Code->prefix.seg = default_reg;
}
} else if( default_reg != EMPTY ) {
switch( reg ) {
case ASSUME_ES:
Code->prefix.seg = PREFIX_ES;
break;
case ASSUME_CS:
Code->prefix.seg = PREFIX_CS;
break;
case ASSUME_DS:
Code->prefix.seg = PREFIX_DS;
break;
case ASSUME_GS:
Code->prefix.seg = PREFIX_GS;
break;
case ASSUME_FS:
Code->prefix.seg = PREFIX_FS;
break;
case ASSUME_SS:
Code->prefix.seg = PREFIX_SS;
break;
default:
break;
}
}
}
int check_override( int *i )
/**************************/
/* Check if there is a register, segment or group override */
{
int index;
index = *i;
if( ( index + 2 ) < Token_Count ) {
if( AsmBuffer[index+1]->token == T_COLON ) {
switch( AsmBuffer[index]->token ) {
case T_REG:
Code->prefix.seg =
AsmOpTable[AsmOpcode[AsmBuffer[index]->value].position].opcode;
(*i) += 2;
if( *i >= Token_Count ) {
AsmError( LABEL_EXPECTED_AFTER_COLON );
return( ERROR );
}
break;
case T_ID: // Segment or Group override
if( FixOverride(*i) != NOT_ERROR ) {
return( ERROR );
}
(*i) += 2;
if( *i >= Token_Count ) {
AsmError( LABEL_EXPECTED_AFTER_COLON );
return( ERROR );
}
break;
default:
break;
}
}
}
return( NOT_ERROR );
}
#endif
static int Reg386( int reg_token )
/********************************/
{
switch( reg_token ) {
case T_EAX: return( 0 );
case T_ECX: return( 1 );
case T_EDX: return( 2 );
case T_EBX: return( 3 );
case T_ESP: return( 4 );
case T_EBP: return( 5 );
case T_ESI: return( 6 );
case T_EDI: return( 7 );
}
/* I don't think this should happen */
return( 0 );
}
int OperandSize( OPNDTYPE opnd )
/******************************/
{
if( ( opnd == OP_NONE ) || ( opnd & OP_SPECIAL ) ) {
return( 0 );
} else if( opnd == OP_M ) {
/* fixme */
switch( Code->mem_type ) {
case MT_EMPTY: return( 0 );
#if defined( _STANDALONE_ )
case MT_SBYTE:
#endif
case MT_BYTE: return( 1 );
#if defined( _STANDALONE_ )
case MT_SWORD:
#endif
case MT_WORD: return( 2 );
#if defined( _STANDALONE_ )
case MT_SDWORD:
#endif
case MT_DWORD: return( 4 );
case MT_FWORD: return( 6 );
case MT_QWORD: return( 8 );
case MT_TBYTE: return( 10 );
case MT_OWORD: return( 16 );
default: break;
}
} else if( opnd & ( OP_M8_R8 | OP_M_B | OP_I8 | OP_I_1 | OP_I_3 | OP_I8_U ) ) {
return( 1 );
} else if( opnd & ( OP_M16_R16 | OP_M_W | OP_I16 | OP_SR ) ) {
return( 2 );
} else if( opnd & ( OP_R32 | OP_M_DW | OP_I32 | OP_J32 | OP_SPEC_REG ) ) {
return( 4 );
} else if( opnd & ( OP_I | OP_J48 ) ) {
return( 6 );
} else if( opnd & ( OP_M_QW | OP_MMX ) ) {
return( 8 );
} else if( opnd & ( OP_STI | OP_M_TB ) ) {
return( 10 );
} else if( opnd & ( OP_M_OW | OP_XMM ) ) {
return( 16 );
}
return( 0 );
}
int InRange( unsigned long val, unsigned bytes )
/**********************************************/
/*
Can 'val' be represented in 'bytes' bytes?
*/
{
unsigned long max;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?