direct.c

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

C
2,214
字号
/****************************************************************************
*
*                            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:  Processing of assembly directives.
*
****************************************************************************/


#include "asmglob.h"
#include <ctype.h>

#include "asmalloc.h"
#include "asmins.h"
#include "asmsym.h"
#include "directiv.h"
#include "queues.h"
#include "asmexpnd.h"
#include "asmdefs.h"
#include "asmfixup.h"
#include "mangle.h"
#include "asmlabel.h"
#include "asminput.h"
#include "asmeval.h"

#include "myassert.h"

#define BIT16           0
#define BIT32           1

#define MAGIC_FLAT_GROUP        ModuleInfo.flat_idx

#define INIT_ALIGN      0x1
#define INIT_COMBINE    0x2
#define INIT_USE        0x4
#define INIT_CLASS      0x8
#define INIT_MEMORY     0x10
#define INIT_STACK      0x20

typedef struct {
      char      *string;        // the token string
      uint      value;          // value connected to this token
      uint      init;           // explained in direct.c ( look at SegDef() )
} typeinfo;

typedef struct {
    asm_sym             *symbol;        /* segment or group that is to
                                           be associated with the register */
    unsigned            error:1;        // the register is assumed to ERROR
    unsigned            flat:1;         // the register is assumed to FLAT
} assume_info;

typedef enum {
    SIM_CODE = 0,
    SIM_STACK,
    SIM_DATA,
    SIM_DATA_UN,            // .DATA?
    SIM_FARDATA,
    SIM_FARDATA_UN,         // .FARDATA?
    SIM_CONST,
    SIM_NONE,
    SIM_LAST = SIM_NONE
} sim_seg;

typedef struct {
    sim_seg     seg;                    // segment id
    char        close[MAX_LINE];        // closing line for this segment
    int_16      stack_size;             // size of stack segment
} last_seg_info;        // information about last opened simplified segment

enum {
#undef fix
#define fix( tok, str, val, init )              tok

#include "directd.h"
};


static typeinfo TypeInfo[] = {

#undef fix
#define fix( tok, string, value, init_val )     { string, value, init_val }

#include "directd.h"
};

#define LOCAL_DEFAULT_SIZE      2
#define DEFAULT_STACK_SIZE      1024

#define ARGUMENT_STRING         " [bp+ "
#define ARGUMENT_STRING_32      " [ebp+ "
#define LOCAL_STRING            " [bp- "
#define LOCAL_STRING_32         " [ebp- "

static char             *Check4Mangler( int *i );
static int              token_cmp( char **token, int start, int end );
static void             ModelAssumeInit( void );

extern  char            write_to_file;  // write if there is no error
extern  uint_32         BufSize;
extern  int_8           DefineProc;     // TRUE if the definition of procedure
                                        // has not ended
extern char             EndDirectiveFound;
extern struct asm_sym   *SegOverride;

seg_list                *CurrSeg;       // points to stack of opened segments
uint                    LnamesIdx;      // Number of LNAMES definition
obj_rec                 *ModendRec;     // Record for Modend

int                     in_prologue;

static assume_info      AssumeTable[ASSUME_LAST];

symbol_queue            Tables[TAB_LAST];// tables of definitions
module_info             ModuleInfo;

static seg_list         *ProcStack = NULL;

static char *StartupDosNear[] = {
        " mov     dx,DGROUP",
        " mov     ds,dx",
        " mov     bx,ss",
        " sub     bx,dx",
        " shl     bx,1",
        " shl     bx,1",
        " shl     bx,1",
        " shl     bx,1",
        " cli     ",
        " mov     ss,dx",
        " add     sp,bx",
        " sti     ",
        NULL
};
static char *StartupDosFar[] = {
        " mov     dx,DGROUP",
        " mov     ds,dx",
        NULL
};
static char *ExitOS2[] = { /* mov al, retval  followed by: */
        " xor ah, ah",
        " push 01h",
        " push ax",
        " call far DOSEXIT",
        NULL
};
static char *ExitDos[] = { /* mov al, retval  followed by: */
        " mov     ah,4ch",
        " int     21h",
        NULL
};
static char *RetVal = " mov    al, ";

static char *StartAddr = "`symbol_reserved_for_start_address`";
static char StartupDirectiveFound = FALSE;

#define DEFAULT_CODE_CLASS      "CODE"
#define DEFAULT_CODE_NAME       "_TEXT"
#define DEFAULT_DATA_NAME       "_DATA"
#define SIM_DATA_OFFSET         5        // strlen("_DATA")
#define SIM_FARDATA_OFFSET      8        // strlen("FAR_DATA")

/* code generated by @startup */

static char *SimCodeBegin[2][ SIM_LAST ] = {
    {
        "_TEXT SEGMENT WORD PUBLIC 'CODE' IGNORE",
        "STACK SEGMENT PARA STACK 'STACK' IGNORE",
        "_DATA SEGMENT WORD PUBLIC 'DATA' IGNORE",
        "_BSS  SEGMENT WORD PUBLIC 'BSS' IGNORE",
        "FAR_DATA SEGMENT PARA PRIVATE 'FAR_DATA' IGNORE",
        "FAR_BSS  SEGMENT PARA PRIVATE 'FAR_BSS' IGNORE",
        "CONST SEGMENT WORD PUBLIC 'CONST' READONLY IGNORE"
    },
    {
        "_TEXT SEGMENT DWORD USE32 PUBLIC 'CODE' IGNORE",
        "STACK SEGMENT DWORD USE32 STACK 'STACK' IGNORE",
        "_DATA SEGMENT DWORD USE32 PUBLIC 'DATA' IGNORE",
        "_BSS  SEGMENT DWORD USE32 PUBLIC 'BSS' IGNORE",
        "FAR_DATA SEGMENT DWORD USE32 PRIVATE 'FAR_DATA' IGNORE",
        "FAR_BSS  SEGMENT DWORD USE32 PRIVATE 'FAR_BSS' IGNORE",
        "CONST SEGMENT DWORD USE32 PUBLIC 'CONST' READONLY IGNORE"
    }
};

static char *SimCodeEnd[ SIM_LAST ] = {
        "_TEXT ENDS",
        "STACK ENDS",
        "_DATA ENDS",
        "_BSS  ENDS",
        "FAR_DATA ENDS",
        "FAR_BSS  ENDS",
        "CONST ENDS"
};

/* Code generated by simplified segment definitions */

static uint             segdefidx;      // Number of Segment definition
static uint             grpdefidx;      // Number of Group definition
static uint             extdefidx;      // Number of External definition
static last_seg_info    lastseg;        // last opened simplified segment

static char *parm_reg[3][4]= {
    { " AL ", " DL ", " BL ", " CL " },
    { " AX ", " DX ", " BX ", " CX " },
    { " EAX ", " EDX ", " EBX ", " ECX " },
};

enum regsize {
    A_BYTE = 0,
    A_WORD,
    A_DWORD,
};


#define ROUND_UP( i, r ) (((i)+((r)-1)) & ~((r)-1))

static int get_watcom_argument_string( char *buffer, uint_8 size, uint_8 *parm_number )
/*************************************************************************************/
/* get the register for parms 0 to 3,
 * using the watcom register parm passing conventions ( A D B C ) */
{
    int parm = *parm_number;

    if( parm > 3 )
        return( FALSE );
    switch( size ) {
    case 1:
        sprintf( buffer, parm_reg[A_BYTE][parm] );
        break;
    case 2:
        sprintf( buffer, parm_reg[A_WORD][parm] );
        break;
    case 4:
        if( Use32 ) {
            sprintf( buffer, parm_reg[A_DWORD][parm] );
            break;
        } else {
            switch( parm ) {
            case 0:
                sprintf( buffer, " [DX AX]" );
                buffer[0] = 0;
                *parm_number = 1; // take up 0 and 1
                break;
            case 1:
            case 2:
                sprintf( buffer, " [CX BX]" );
                buffer[0] = 0;
                *parm_number = 3; // take up 2 and 3
                break;
            default:
                // passed on stack ... it's ok
                return( FALSE );
            }
            return( TRUE );
        }
    case 10:
        AsmErr( TBYTE_NOT_SUPPORTED );
        return( ERROR );
    case 6:
        if( Use32 ) {
            switch( parm ) {
            case 0:
                sprintf( buffer, " [DX EAX]" );
                buffer[0]=0;
                *parm_number = 1; // take up 0 and 1
                break;
            case 1:
            case 2:
                sprintf( buffer, " [CX EBX]" );
                buffer[0]=0;
                *parm_number = 3; // take up 2 and 3
                break;
            default:
                // passed on stack ... it's ok
                return( FALSE );
            }
            return( TRUE );
        }
        // fall through for 16 bit to default
    case 8:
        if( Use32 ) {
            switch( parm ) {
            case 0:
                sprintf( buffer, " [EDX EAX]" );
                buffer[0]=0;
                *parm_number = 1; // take up 0 and 1
                break;
            case 1:
            case 2:
                sprintf( buffer, " [ECX EBX]" );
                buffer[0]=0;
                *parm_number = 3; // take up 2 and 3
                break;
            default:
                // passed on stack ... it's ok
                return( FALSE );
            }
            return( TRUE );
        }
        // fall through for 16 bit to default
    default:
        // something wierd
        AsmError( STRANGE_PARM_TYPE );
        return( ERROR );
    }
    return( TRUE );
}

#ifdef DEBUG_OUT
void heap( char *func ) // for debugging only
/*********************/
{
    switch(_heapchk()) {
    case _HEAPBADNODE:
    case _HEAPBADBEGIN:
    DebugMsg(("Function : %s - ", func ));
        DebugMsg(("ERROR - heap is damaged\n"));
        exit(1);
        break;
    default:
        break;
    }
}
#endif

void IdxInit( void )
/******************/
{
    LnamesIdx   = 0;
    segdefidx   = 0;
    grpdefidx   = 0;
    extdefidx   = 0;
}

static int SetAssumeCSCurrSeg( void )
/*************************************/
{
    assume_info     *info;

    info = &(AssumeTable[ ASSUME_CS ]);
    if( CurrSeg == NULL ) {
        info->symbol = NULL;
        info->flat = FALSE;
        info->error = TRUE;
    } else {
        if( CurrSeg->seg->e.seginfo->group != NULL )
            info->symbol = GetGrp( &CurrSeg->seg->sym );
        else
            info->symbol = &CurrSeg->seg->sym;
        info->flat = FALSE;
        info->error = FALSE;
    }
    return( NOT_ERROR );
}

void push( void **stack, void *elt )
/**********************************/
{
    stacknode *node;

    node = AsmAlloc( sizeof( stacknode ));
    node->next = *stack;
    node->elt = elt;
    *stack = node;
}

void *pop( void **stack )
/***********************/
{
    stacknode   *node;
    void        *elt;

    node = (stacknode *)(*stack);
    *stack = node->next;
    elt = node->elt;
    AsmFree( node );
    return( elt );
}

static int push_seg( dir_node *seg )
/**********************************/
/* Push a segment into the current segment stack */
{
    seg_list    *curr;

    for( curr = CurrSeg; curr; curr = curr->next ) {
        if( curr->seg == seg ) {
            AsmError( BLOCK_NESTING_ERROR );
            return( ERROR );
        }
    }
    push( &CurrSeg, seg );
    SetAssumeCSCurrSeg();
    return( NOT_ERROR );
}

static dir_node *pop_seg( void )
/******************************/
/* Pop a segment out of the current segment stack */
{
    dir_node    *seg;

    /**/myassert( CurrSeg != NULL );
    seg = pop( &CurrSeg );
    SetAssumeCSCurrSeg();
    return( seg );
}

static void push_proc( dir_node *proc )
/*************************************/
{
    push( &ProcStack, proc );
    return;
}

static dir_node *pop_proc( void )
/*******************************/
{
    if( ProcStack == NULL )
        return( NULL );
    return( (dir_node *)pop( &ProcStack ) );

⌨️ 快捷键说明

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