#include <ctype.h>
#include "globals.h"
#include "memalloc.h"
#include "parser.h"
#include "segment.h"
#include "lqueue.h"
#include "expreval.h"
#include "fastpass.h"
#include "listing.h"
#include "msgtext.h"
#include "tokenize.h"
#include "proc.h"
#include "cpumodel.h"
#include "equate.h"
#include "myassert.h"
#define DEFAULT_STACK_SIZE 1024
extern const char szDgroup[];
static char *SegmNames[ SIM_LAST ];
static const char * const SegmNamesDef[ SIM_LAST ] = {
"_TEXT", "STACK", "_DATA", "_BSS", "FAR_DATA", "FAR_BSS", "CONST"
};
static const char * const SegmClass[ SIM_LAST ] = {
"CODE", "STACK", "DATA", "BSS", "FAR_DATA", "FAR_BSS", "CONST"
};
static const char * const SegmCombine[ SIM_LAST ] = {
"PUBLIC", "STACK", "PUBLIC", "PUBLIC", "PRIVATE", "PRIVATE", "PUBLIC"
};
char *SimGetSegName( enum sim_seg segno )
{
char* segn;
segn = SegmNames[segno];
if (segn == NULL && ModuleInfo.flat == TRUE)
segn = "_flat";
return( segn );
}
const char *GetCodeClass( void )
{
if ( Options.names[OPTN_CODE_CLASS] )
return( Options.names[OPTN_CODE_CLASS] );
return( SegmClass[SIM_CODE] );
}
static void AddToDgroup( enum sim_seg segm, const char *name )
{
if( ModuleInfo.model == MODEL_FLAT
|| Options.output_format == OFORMAT_COFF
|| Options.output_format == OFORMAT_ELF)
return;
if( name == NULL )
name = SegmNames[segm];
AddLineQueueX( "%s %r %s", szDgroup, T_GROUP, name );
}
static void close_currseg( void )
{
if ( CurrSeg ) {
DebugMsg1(("close_currseg: current seg=%s\n", CurrSeg->sym.name));
AddLineQueueX( "%s %r", CurrSeg->sym.name, T_ENDS );
}
}
static void SetSimSeg( enum sim_seg segm, const char *name )
{
char *pAlign = "WORD";
char *pAlignSt = "PARA";
char *pUse = "";
char align[16];
struct asym *sym;
const char *pFmt;
const char *pClass;
if (Options.seg_align != 4)
{
sprintf(align, "ALIGN(%d)", (1 << Options.seg_align));
pAlignSt = align;
}
if ( ModuleInfo.defOfssize > USE16 ) {
if ( ModuleInfo.model == MODEL_FLAT )
pUse = "FLAT";
else
pUse = "USE32";
if (Options.seg_align != 4)
pAlign = align;
else if ((ModuleInfo.curr_cpu & P_CPU_MASK) <= P_386)
pAlign = "DWORD";
else
pAlign = "PARA";
pAlignSt = pAlign;
}
if ( segm == SIM_CODE )
pClass = GetCodeClass();
else
pClass = SegmClass[segm];
if ( segm == SIM_STACK || segm == SIM_FARDATA || segm == SIM_FARDATA_UN )
pAlign = pAlignSt;
pFmt = "%s %r %s %s %s '%s'";
if ( name == NULL ) {
name = SegmNames[segm];
if (name == NULL && ModuleInfo.flat) name = "_flat";
if (name == NULL) name = "_TEXT";
if ( ModuleInfo.simseg_init & ( 1 << segm ) )
pFmt = "%s %r";
else {
ModuleInfo.simseg_init |= ( 1 << segm );
if ( Parse_Pass == PASS_1 ) {
sym = SymSearch( name );
if ( sym && sym->state == SYM_SEG && sym->isdefined == TRUE )
ModuleInfo.simseg_defd |= ( 1 << segm );
}
if ( ModuleInfo.simseg_defd & ( 1 << segm ) )
pFmt = "%s %r";
}
} else {
sym = SymSearch( name );
if ( sym && sym->state == SYM_SEG && sym->isdefined == TRUE )
pFmt = "%s %r";
}
if (ModuleInfo.flat)
{
pUse = "USE64";
pFmt = "%s %r %s %s %s '%s'";
AddLineQueueX(pFmt, "_flat", T_SEGMENT, "BYTE", "USE16", "PUBLIC", "CODE");
AddLineQueueX("assume cs:_flat, ds:_flat, es:_flat, ss:_flat, fs:_flat, gs:_flat");
if (Parse_Pass == PASS_1)
{
sym_CodeSize = CreateVariable("@CodeSize", 0);
sym_CodeSize->predefined = TRUE;
sym_DataSize = CreateVariable("@DataSize", 0);
sym_DataSize->predefined = TRUE;
sym_ReservedStack = CreateVariable("@ReservedStack", 0);
sym_ReservedStack->predefined = TRUE;
}
FStoreLine(0);
}
else
{
AddLineQueueX(pFmt, name, T_SEGMENT, pAlign, pUse, SegmCombine[segm], pClass);
}
return;
}
static void EndSimSeg( enum sim_seg segm )
{
AddLineQueueX( "%s %r", SegmNames[segm], T_ENDS );
return;
}
ret_code SimplifiedSegDir( int i, struct asm_tok tokenarray[] )
{
const char *name = NULL;
char init;
int type;
struct expr opndx;
DebugMsg1(("SimplifiedSegDir(%s) enter\n", tokenarray[i].string_ptr ));
if( ModuleInfo.model == MODEL_NONE ) {
RewindToWin64();
return( ERROR );
}
LstWrite(LSTTYPE_DIRECTIVE, 0, NULL);
type = GetSflagsSp( tokenarray[i].tokval );
i++;
if( type == SIM_STACK ) {
if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR )
return( ERROR );
if( opndx.kind == EXPR_EMPTY )
opndx.value = DEFAULT_STACK_SIZE;
else if( opndx.kind != EXPR_CONST ) {
EmitError( CONSTANT_EXPECTED );
return( ERROR );
}
} else {
if( tokenarray[i].token == T_ID &&
( type == SIM_CODE || type == SIM_FARDATA || type == SIM_FARDATA_UN
|| ( Options.strict_masm_compat == FALSE &&
( type == SIM_DATA || type == SIM_DATA_UN || type == SIM_CONST )))) {
name = tokenarray[i].string_ptr;
i++;
}
}
if ( tokenarray[i].token != T_FINAL ) {
EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
return( ERROR );
}
if (type != SIM_STACK)
{
close_currseg();
}
if ( name == NULL )
init = ( ModuleInfo.simseg_init & ( 1 << type ) );
switch( type ) {
case SIM_CODE:
SetSimSeg( SIM_CODE, name );
if( ModuleInfo.model == MODEL_TINY ) {
if ( name )
AddToDgroup( SIM_CODE, name );
name = szDgroup;
} else if( ModuleInfo.model == MODEL_FLAT ) {
name = "FLAT";
} else {
if( name == NULL )
name = SegmNames[SIM_CODE];
}
AddLineQueueX( "%r %r:%s", T_ASSUME, T_CS, name );
break;
case SIM_STACK:
SetSimSeg( SIM_STACK, NULL );
AddLineQueueX( "ORG 0%xh", opndx.value );
EndSimSeg( SIM_STACK );
if ( !init )
if ( ModuleInfo.distance != STACK_FAR )
AddToDgroup( SIM_STACK, NULL );
break;
case SIM_DATA:
SetSimSeg(type, name);
AddLineQueueX("%r %r:ERROR", T_ASSUME, T_CS);
if (name || (!init))
AddToDgroup(type, name);
break;
case SIM_DATA_UN:
if (Options.output_format == OFORMAT_BIN && Options.sub_format != SFORMAT_PE && ModuleInfo.flat)
{
EmitWarn(2, UNINIT_DATA_IN_BIN);
}
case SIM_CONST:
SetSimSeg( type, name );
AddLineQueueX( "%r %r:ERROR", T_ASSUME, T_CS );
if ( name || (!init) )
AddToDgroup( type, name );
break;
case SIM_FARDATA:
case SIM_FARDATA_UN:
SetSimSeg( type, name );
AddLineQueueX( "%r %r:ERROR", T_ASSUME, T_CS );
break;
default:
myassert( 0 );
break;
}
RunLineQueue();
return( NOT_ERROR );
}
void SetModelDefaultSegNames( void )
{
memcpy( SegmNames, SegmNamesDef, sizeof(SegmNames) );
if( Options.names[OPTN_TEXT_SEG] ) {
SegmNames[SIM_CODE] = LclAlloc( strlen( Options.names[OPTN_TEXT_SEG] ) + 1 );
strcpy( SegmNames[SIM_CODE], Options.names[OPTN_TEXT_SEG] );
} else {
if ( SIZE_CODEPTR & ( 1 << ModuleInfo.model ) ) {
SegmNames[SIM_CODE] = LclAlloc( strlen( SegmNamesDef[SIM_CODE] ) + strlen( ModuleInfo.name ) + 1 );
strcpy( SegmNames[SIM_CODE], ModuleInfo.name );
strcat( SegmNames[SIM_CODE], SegmNamesDef[SIM_CODE] );
}
}
if ( Options.names[OPTN_DATA_SEG] ) {
SegmNames[SIM_DATA] = LclAlloc( strlen( Options.names[OPTN_DATA_SEG] ) + 1 );
strcpy( SegmNames[SIM_DATA], Options.names[OPTN_DATA_SEG] );
}
return;
}
ret_code ModelSimSegmInit( int model )
{
char buffer[20];
ModuleInfo.simseg_init = 0;
SetSimSeg( SIM_CODE, NULL );
EndSimSeg( SIM_CODE );
SetSimSeg( SIM_DATA, NULL ) ;
EndSimSeg( SIM_DATA );
if( model != MODEL_FLAT &&
( Options.output_format == OFORMAT_OMF
|| Options.output_format == OFORMAT_BIN)) {
strcpy( buffer, "%s %r %s" );
if( model == MODEL_TINY ) {
strcat( buffer, ", %s" );
AddLineQueueX( buffer, szDgroup, T_GROUP, SegmNames[SIM_CODE], SegmNames[SIM_DATA] );
} else
AddLineQueueX( buffer, szDgroup, T_GROUP, SegmNames[SIM_DATA] );
}
return( NOT_ERROR );
}
void ModelSimSegmExit( void )
{
if ( CurrSeg ) {
close_currseg();
RunLineQueue();
}
}