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