📄 cprag86.c
字号:
if( CurToken == T_CONSTANT ) {
if( i < MAXIMUM_BYTESEQ ) {
buff[ i++ ] = Constant;
} else {
if( ! too_many_bytes ) {
CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
too_many_bytes = 1;
}
}
NextToken();
} else {
fixword = FixupKeyword();
if( fixword == FIXWORD_NONE ) break;
if( fixword == FIXWORD_FLOAT ) {
#if _CPU == 8086
AddAFix( i, NULL, FIX_SEG, 0 );
#endif
} else { /* seg or offset */
if( CurToken != T_ID ) {
CErr1( ERR_EXPECTING_ID );
} else {
name = CStrSave( Buffer );
offset = 0;
NextToken();
if( CurToken == T_PLUS ) {
NextToken();
if( CurToken == T_CONSTANT ) {
offset = Constant;
NextToken();
}
} else if( CurToken == T_MINUS ) {
NextToken();
if( CurToken == T_CONSTANT ) {
offset = -Constant;
NextToken();
}
}
}
switch( fixword ) {
case FIXWORD_RELOFF:
#if _CPU == 8086
AddAFix( i, name, FIX_RELOFF16, offset );
i += 2;
#else
AddAFix( i, name, FIX_RELOFF32, offset );
i += 4;
#endif
break;
case FIXWORD_OFFSET:
#if _CPU == 8086
AddAFix( i, name, FIX_OFF16, offset );
i += 2;
#else
AddAFix( i, name, FIX_OFF32, offset );
i += 4;
#endif
break;
case FIXWORD_SEGMENT:
AddAFix( i, name, FIX_SEG, 0 );
i += 2;
break;
}
if( i > MAXIMUM_BYTESEQ ) {
if( ! too_many_bytes ) {
CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
too_many_bytes = 1;
}
}
}
}
}
if( too_many_bytes ) {
FreeAsmFixups();
uses_auto = 0;
} else {
uses_auto = InsertFixups( buff, i );
}
CompFlags.pre_processing = 2;
#if _CPU == 8086 || _CPU == 386
AsmSymFini();
#endif
return( uses_auto );
}
hw_reg_set PragRegName( char *str )
{
int i;
char *p;
hw_reg_set name;
if( *str == '_' ) {
++str;
if( *str == '_' ) {
++str;
}
}
i = 0;
p = Registers;
while( *p != '\0' ) {
if( stricmp( p, str ) == 0 ) return( RegBits[ i ] );
i++;
while( *p++ != '\0' ) {;}
}
if( strcmp( str, "8087" ) == 0 ) {
HW_CAsgn( name, HW_FLTS );
} else {
HW_CAsgn( name, HW_EMPTY );
}
return( name );
}
local void GetParmInfo( void )
{
struct {
unsigned f_pop : 1;
unsigned f_reverse : 1;
unsigned f_loadds : 1;
unsigned f_nomemory : 1;
unsigned f_list : 1;
} have;
have.f_pop = 0;
have.f_reverse = 0;
have.f_loadds = 0;
have.f_nomemory = 0;
have.f_list = 0;
for( ;; ) {
if( !have.f_pop && PragRecog( "caller" ) ) {
CurrInfo->class |= CALLER_POPS;
have.f_pop = 1;
} else if( !have.f_pop && PragRecog( "routine" ) ) {
CurrInfo->class &= ~ CALLER_POPS;
have.f_pop = 1;
} else if( !have.f_reverse && PragRecog( "reverse" ) ) {
CurrInfo->class |= REVERSE_PARMS;
have.f_reverse = 1;
} else if( !have.f_nomemory && PragRecog( "nomemory" ) ) {
CurrInfo->class |= NO_MEMORY_READ;
have.f_nomemory = 1;
} else if( !have.f_loadds && PragRecog( "loadds" ) ) {
CurrInfo->class |= LOAD_DS_ON_CALL;
have.f_loadds = 1;
} else if( !have.f_list && PragSet() != T_NULL ) {
PragManyRegSets();
have.f_list = 1;
} else {
break;
}
}
}
local void GetRetInfo( void )
{
struct {
unsigned f_no8087 : 1;
unsigned f_list : 1;
unsigned f_struct : 1;
} have;
have.f_no8087 = 0;
have.f_list = 0;
have.f_struct = 0;
CurrInfo->class &= ~ NO_8087_RETURNS; /* 29-mar-90 */
for( ;; ) {
if( !have.f_no8087 && PragRecog( "no8087" ) ) {
have.f_no8087 = 1;
HW_CTurnOff( CurrInfo->returns, HW_FLTS );
CurrInfo->class |= NO_8087_RETURNS;
} else if( !have.f_list && PragSet() != T_NULL ) {
have.f_list = 1;
CurrInfo->class |= SPECIAL_RETURN;
CurrInfo->returns = PragRegList();
} else if( !have.f_struct && PragRecog( "struct" ) ) {
have.f_struct = 1;
GetSTRetInfo();
} else {
break;
}
}
}
local void GetSTRetInfo( void )
{
struct {
unsigned f_float : 1;
unsigned f_struct : 1;
unsigned f_allocs : 1;
unsigned f_list : 1;
} have;
have.f_float = 0;
have.f_struct = 0;
have.f_allocs = 0;
have.f_list = 0;
for( ;; ) {
if( !have.f_float && PragRecog( "float" ) ) {
have.f_float = 1;
CurrInfo->class |= NO_FLOAT_REG_RETURNS;
} else if( !have.f_struct && PragRecog( "struct" ) ) {
have.f_struct = 1;
CurrInfo->class |= NO_STRUCT_REG_RETURNS;
} else if( !have.f_allocs && PragRecog( "routine" ) ) {
have.f_allocs = 1;
CurrInfo->class |= ROUTINE_RETURN;
} else if( !have.f_allocs && PragRecog( "caller" ) ) {
have.f_allocs = 1;
CurrInfo->class &= ~ROUTINE_RETURN;
} else if( !have.f_list && PragSet() != T_NULL ) {
have.f_list = 1;
CurrInfo->class |= SPECIAL_STRUCT_RETURN;
CurrInfo->streturn = PragRegList();
} else {
break;
}
}
}
local void GetSaveInfo( void )
{
hw_reg_set modlist;
hw_reg_set default_flt_n_seg;
hw_reg_set flt_n_seg;
struct {
unsigned f_exact : 1;
unsigned f_nomemory : 1;
unsigned f_list : 1;
} have;
have.f_exact = 0;
have.f_nomemory = 0;
have.f_list = 0;
for( ;; ) {
if( !have.f_exact && PragRecog( "exact" ) ) {
CurrInfo->class |= MODIFY_EXACT;
have.f_exact = 1;
} else if( !have.f_nomemory && PragRecog( "nomemory" ) ) {
CurrInfo->class |= NO_MEMORY_CHANGED;
have.f_nomemory = 1;
} else if( !have.f_list && PragSet() != T_NULL ) {
modlist = PragRegList();
have.f_list = 1;
} else {
break;
}
}
if( have.f_list ) {
HW_Asgn( default_flt_n_seg, DefaultInfo.save );
HW_CTurnOn( CurrInfo->save, HW_FULL );
if( !have.f_exact && !CompFlags.save_restore_segregs ) {
HW_CAsgn( flt_n_seg, HW_FLTS );
HW_CTurnOn( flt_n_seg, HW_SEGS );
HW_TurnOff( CurrInfo->save, flt_n_seg );
HW_OnlyOn( default_flt_n_seg, flt_n_seg );
HW_TurnOn( CurrInfo->save, default_flt_n_seg );
}
HW_TurnOff( CurrInfo->save, modlist );
}
}
void GetAsmLine()
{
char buf[256];
CompFlags.pre_processing = 1; // cause T_NULL token at end of line
if( strcmp( Buffer, "_emit" ) == 0 ) {
NextToken(); // get numeric constant
if( CurToken != T_CONSTANT ) {
ExpectConstant();
} else {
CodeBuffer[Address++] = Constant;
NextToken();
}
} else {
buf[0] = '\0';
for(;;) {
if( CurToken == T_SEMI_COLON ) {
// ; .ASM comment
for(;;) {
NextToken();
if( CurToken == T_EOF ) break;
if( CurToken == T_NULL ) break;
}
break;
}
if( CurToken == T_EOF ) break;
if( CurToken == T_NULL ) break;
if( CurToken == T___ASM ) break;
if( CurToken == T_RIGHT_BRACE ) break;
strncat( buf, Buffer, 255 );
if( CurToken != T_DOT )
strncat( buf, " ", 255 );
NextToken();
}
AsmLine( buf );
}
CompFlags.pre_processing = 0; // cause T_NULL token at end of line
}
static void MakeInlineAsmFunc( unsigned char *buff )
{
int i;
SYM_HANDLE sym_handle;
TREEPTR tree;
int uses_auto;
auto char name[8];
i = Address;
if( i != 0 ) {
sprintf( name, "F.%d", AsmFuncNum );
++AsmFuncNum;
CreateAux( name );
*CurrInfo = DefaultInfo;
CurrInfo->use = 1;
CurrInfo->save = AsmRegsSaved; // indicate no registers saved
uses_auto = InsertFixups( buff, i );
if( uses_auto ) {
/*
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 );
}
CurrEntry->info = CurrInfo;
CurrEntry->next = AuxList;
AuxList = CurrEntry;
CurrEntry = NULL;
sym_handle = MakeFunction( CStrSave( name ),
FuncNode( GetType( TYPE_VOID ), 0, NULL ) );
tree = LeafNode( OPR_FUNCNAME );
tree->op.sym_handle = sym_handle;
tree = ExprNode( tree, OPR_CALL, NULL );
tree->expr_type = GetType( TYPE_VOID );
AddStmt( tree );
}
}
void AsmStmt()
{
int too_many_bytes;
auto unsigned char buff[ MAXIMUM_BYTESEQ + 32 ];
// indicate that we are inside an __asm statement so scanner will
// allow tokens unique to the assembler. e.g. 21h
CompFlags.inside_asm_stmt = 1;
NextToken();
CodeBuffer = &buff[0];
Address = 0;
if( CurToken == T_LEFT_BRACE ) {
NextToken();
too_many_bytes = 0;
for(;;) { // grab assembler lines
GetAsmLine();
if( Address >= MAXIMUM_BYTESEQ ) {
if( ! too_many_bytes ) {
CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
too_many_bytes = 1;
}
Address = 0; // reset index to we don't overrun buffer
}
if( CurToken == T_RIGHT_BRACE ) break;
if( CurToken == T_EOF ) break;
NextToken();
}
CompFlags.pre_processing = 0;
CompFlags.inside_asm_stmt = 0;
MakeInlineAsmFunc( buff );
NextToken();
} else {
GetAsmLine(); // grab single assembler instruction
CompFlags.pre_processing = 0;
CompFlags.inside_asm_stmt = 0;
MakeInlineAsmFunc( buff );
if( CurToken == T_NULL ) {
NextToken();
}
}
AsmSymFini();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -