cpragx86.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,416 行 · 第 1/3 页
C
1,416 行
doPragAux();
PPState = PPS_EOL | PPS_NO_EXPAND;
}
typedef enum
{ FIXWORD_NONE
, FIXWORD_FLOAT
, FIXWORD_SEGMENT
, FIXWORD_OFFSET
, FIXWORD_RELOFF
} fix_words;
static fix_words FixupKeyword(
void )
{
fix_words retn; // - return
if( CurToken == T_FLOAT ) {
NextToken();
retn = FIXWORD_FLOAT;
} else if( PragRecog( "seg" ) ) {
retn = FIXWORD_SEGMENT;
} else if( PragRecog( "offset" ) ) {
retn = FIXWORD_OFFSET;
} else if( PragRecog( "reloff" ) ) {
retn = FIXWORD_RELOFF;
} else {
retn = FIXWORD_NONE;
}
return( retn );
}
enum sym_state AsmQueryExternal(
char *name )
{
#if 1
SYMBOL sym;
enum sym_state state;
state = SYM_UNDEFINED;
sym = ScopeASMLookup( name );
if( sym != NULL ) {
if( SymIsAutomatic( sym ) ) {
state = SYM_STACK;
} else {
state = SYM_EXTERNAL;
}
}
return( state );
#else
name = name;
return( SYM_UNDEFINED );
#endif
}
#if _CPU == 8086
#define SYM_INT SYM_INT2
#define SYM_FFAR SYM_FAR2
#define SYM_FNEAR SYM_NEAR2
#define SYM_DFAR SYM_INT4
#define SYM_DNEAR SYM_INT2
#else
#define SYM_INT SYM_INT4
#define SYM_FFAR SYM_FAR4
#define SYM_FNEAR SYM_NEAR2
#define SYM_DFAR SYM_INT6
#define SYM_DNEAR SYM_INT4
#endif
#ifdef WCPP_ASM
static enum sym_type CodePtrType( type_flag flags )
{
enum sym_type retn;
if( flags & TF1_FAR ) {
retn = SYM_FFAR;
} else if( flags & TF1_NEAR ) {
retn = SYM_FNEAR;
} else if( TargetSwitches & BIG_CODE ) {
retn = SYM_FFAR;
} else {
retn = SYM_FNEAR;
}
return retn;
}
#endif
static enum sym_type PtrType( type_flag flags )
{
enum sym_type retn;
if( flags & ( TF1_FAR | TF1_HUGE ) ) {
retn = SYM_DFAR;
} else if( flags & TF1_NEAR ) {
retn = SYM_DNEAR;
} else if( TargetSwitches & BIG_DATA ) {
retn = SYM_DFAR;
} else {
retn = SYM_DNEAR;
}
return retn;
}
#ifdef WCPP_ASM
#define ENTRY_ERROR 0,
#define ENTRY_BOOL SYM_INT1,
#define ENTRY_CHAR SYM_INT1,
#define ENTRY_SCHAR SYM_INT1,
#define ENTRY_UCHAR SYM_INT1,
#define ENTRY_WCHAR SYM_INT2,
#define ENTRY_SSHORT SYM_INT2,
#define ENTRY_USHORT SYM_INT2,
#define ENTRY_SINT SYM_INT,
#define ENTRY_UINT SYM_INT,
#define ENTRY_SLONG SYM_INT4,
#define ENTRY_ULONG SYM_INT4,
#define ENTRY_SLONG64 SYM_INT8,
#define ENTRY_ULONG64 SYM_INT8,
#define ENTRY_FLOAT SYM_FLOAT4,
#define ENTRY_DOUBLE SYM_FLOAT8,
#define ENTRY_LONG_DOUBLE SYM_FLOAT8,
#define ENTRY_ENUM 0,
#define ENTRY_POINTER 0,
#define ENTRY_TYPEDEF 0,
#define ENTRY_CLASS 0,
#define ENTRY_BITFIELD 0,
#define ENTRY_FUNCTION 0,
#define ENTRY_ARRAY 0,
#define ENTRY_DOT_DOT_DOT 0,
#define ENTRY_VOID SYM_INT1,
#define ENTRY_MODIFIER 0,
#define ENTRY_MEMBER_POINTER 0,
#define ENTRY_GENERIC 0,
static enum sym_type AsmDataType[] = {
#include "type_arr.h"
};
#endif
#ifdef WCPP_ASM
#define ASM_BLOCK (64)
static enum sym_type AsmType(
TYPE type )
{
type_flag mod_flags;
type = TypeModFlags( type, &mod_flags );
switch( type->id ) {
case TYP_POINTER :
type = TypeModFlags( type->of, &mod_flags );
if( type->id == TYP_FUNCTION ) {
return( CodePtrType( mod_flags ) );
} else {
return( PtrType( mod_flags ) );
}
break;
case TYP_ARRAY :
case TYP_BITFIELD :
case TYP_ENUM :
return( AsmType( type->of ) );
break;
case TYP_CLASS :
return( SYM_INT1 );
break;
case TYP_FUNCTION :
return( CodePtrType( mod_flags ) );
break;
default:
return( AsmDataType[ type->id ] );
break;
}
}
#endif
enum sym_type AsmQueryType( char *name )
{
#if 1
SYMBOL sym;
enum sym_type type;
sym = ScopeASMLookup( name );
if( sym != NULL ) {
type = AsmType( sym->sym_type );
} else {
type = SYM_INT1;
}
return( type );
#else
name = name;
return( SYM_INT1 );
#endif
}
static int insertFixups( VBUF *code_buffer, unsigned char *buff, unsigned i )
{
struct asmfixup *fix;
struct asmfixup *head;
struct asmfixup *chk;
struct asmfixup *next;
struct asmfixup **owner;
unsigned char *src;
unsigned char *end;
unsigned char cg_fix;
unsigned long perform_fixups;
byte_seq *seq;
SYMBOL sym;
char *name;
unsigned dst;
unsigned skip;
int mutate_to_segment;
boolean uses_auto;
#if _CPU == 8086
int fixup_padding;
#endif
uses_auto = FALSE;
perform_fixups = 0;
head = FixupHead;
if( head != NULL ) {
FixupHead = NULL;
/* sort the fixup list in increasing fixup_loc's */
for( fix = head; fix != NULL; fix = next ) {
owner = &FixupHead;
for( ;; ) {
chk = *owner;
if( chk == NULL ) break;
if( chk->fixup_loc > fix->fixup_loc ) break;
owner = &chk->next;
}
next = fix->next;
fix->next = *owner;
*owner = fix;
}
dst = 0;
src = buff;
end = src + i;
fix = FixupHead;
owner = &FixupHead;
/* insert fixup escape sequences */
while( src < end ) {
/* reserve at least ASM_BLOCK bytes in the buffer */
VbufReqd( code_buffer, ( (dst+ASM_BLOCK) + (ASM_BLOCK-1) ) & ~(ASM_BLOCK-1) );
if( fix != NULL && fix->fixup_loc == (src - buff) ) {
name = fix->name;
if( name != NULL ) {
sym = ScopeASMUseSymbol( name, &uses_auto );
if( sym == NULL ) {
return( 0 );
}
}
/* insert fixup information */
skip = 0;
code_buffer->buf[ dst++ ] = FLOATING_FIXUP_BYTE;
mutate_to_segment = 0;
#if _CPU == 8086
fixup_padding = 0;
#endif
switch( fix->fixup_type ) {
case FIX_SEG:
if( name == NULL ) {
/* special case for floating point fixup */
if( src[0] == 0x9b ) {
// FWAIT instruction as first byte
} else if( ( src[0] == 0x90 ) && ( src[1] == 0x9B ) ) {
// inline assembler FWAIT instruction 0x90, 0x9b
} else if( ( src[0] & 0xd8 ) == 0xd8 ) {
// FPU instruction, add FWAIT before it
code_buffer->buf[ dst++ ] = 0x9b;
} else {
// FIXME - probably wrong use of float !!!!
}
} else {
skip = 2;
cg_fix = FIX_SYM_SEGMENT;
}
break;
case FIX_RELOFF8:
CErr2p( ERR_ASSEMBLER_ERROR, "cannot reach label with short jump" );
break;
case FIX_RELOFF16:
skip = 2;
cg_fix = FIX_SYM_RELOFF;
break;
case FIX_RELOFF32:
skip = 4;
cg_fix = FIX_SYM_RELOFF;
#if _CPU == 8086
fixup_padding = 1;
#endif
break;
case FIX_PTR16:
mutate_to_segment = 1;
/* fall through */
case FIX_OFF16:
skip = 2;
cg_fix = FIX_SYM_OFFSET;
break;
case FIX_PTR32:
mutate_to_segment = 1;
/* fall through */
case FIX_OFF32:
skip = 4;
cg_fix = FIX_SYM_OFFSET;
#if _CPU == 8086
fixup_padding = 1;
#endif
break;
}
if( skip != 0 ) {
code_buffer->buf[ dst++ ] = cg_fix;
*((unsigned long *)&code_buffer->buf[dst]) = (unsigned long)sym;
dst += sizeof( long );
*((unsigned long *)&code_buffer->buf[dst]) = fix->offset;
dst += sizeof( long );
src += skip;
}
#if _CPU == 8086
if( fixup_padding ) {
// add offset fixup padding to 32-bit
// cg create only 16-bit offset fixup
code_buffer->buf[ dst++ ] = 0;
code_buffer->buf[ dst++ ] = 0;
//
}
#endif
if( mutate_to_segment ) {
/*
Since the CG escape sequences don't allow for
FAR pointer fixups, we have to split them into two.
This is done by doing the offset fixup first, then
mutating the fixup structure to look like a segment
fixup one near pointer size later.
*/
fix->fixup_type = FIX_SEG;
fix->fixup_loc += skip;
fix->offset = 0;
} else {
head = fix;
fix = fix->next;
if( head->external ) {
*owner = fix;
CMemFree( head->name );
CMemFree( head );
} else {
owner = &head->next;
}
}
} else {
if( *src == FLOATING_FIXUP_BYTE ) {
code_buffer->buf[ dst++ ] = FLOATING_FIXUP_BYTE;
}
code_buffer->buf[ dst++ ] = *src++;
}
VbufUsed( code_buffer, dst );
}
buff = code_buffer->buf;
i = dst;
perform_fixups = DO_FLOATING_FIXUPS;
}
seq = CMemAlloc( offsetof( byte_seq, data ) + i );
seq->length = i | perform_fixups;
memcpy( seq->data, buff, i );
CurrInfo->code = seq;
return( uses_auto );
}
static void AddAFix(
unsigned i,
char *name,
unsigned type,
unsigned long off )
{
struct asmfixup *fix;
fix = (struct asmfixup *)CMemAlloc( sizeof( *fix ) );
fix->external = 1;
fix->fixup_loc = i;
fix->name = name;
fix->offset = off;
fix->fixup_type = type;
fix->next = FixupHead;
FixupHead = fix;
}
static byte_seq *AuxCodeDup( // DUPLICATE AUX CODE
byte_seq *code )
{
byte_seq *new_code;
byte_seq_len code_length;
byte_seq_len size;
if( code == NULL ) {
return( code );
}
code_length = code->length & MAX_BYTE_SEQ_LEN;
size = offsetof( byte_seq, data ) + code_length;
new_code = (byte_seq *)vctsave( (char *)code, size );
return( new_code );
}
void AsmSysCopyCode( void )
/*************************/
{
byte_seq *code;
code = CurrInfo->code;
if( code != NULL && code == CurrAlias->code ) {
CurrInfo->code = AuxCodeDup( code );
}
}
boolean AsmSysInsertFixups( VBUF *code )
/**************************************/
{
boolean uses_auto;
auto VBUF temp_buffer;
VbufInit( &temp_buffer );
VbufReqd( &temp_buffer, code->used );
uses_auto = insertFixups( &temp_buffer, code->buf, code->used );
VbufFree( &temp_buffer );
AsmSymFini();
return( uses_auto );
}
AUX_INFO *AsmSysCreateAux( char *name )
/*************************************/
{
CreateAux( name );
AuxCopy( CurrInfo, &WatcallInfo );
CurrInfo->use = 1;
CurrInfo->save = asmRegsSaved;
CurrEntry->info = CurrInfo;
return( CurrInfo );
}
void AsmSysUsesAuto( void )
/*************************/
{
/*
We want to force the calling routine to set up a [E]BP frame
for the use of this pragma. This is done by saying the pragma
modifies the [E]SP register. A kludge, but it works.
*/
HW_CTurnOff( CurrInfo->save, HW_SP );
ScopeASMUsesAuto();
}
char const *AsmSysDefineByte( void )
/**********************************/
{
return( "db" );
}
void AsmSysDone( void )
/*********************/
{
PragEnding( FALSE );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?