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