📄 cprag86.c
字号:
/****************************************************************************
*
* 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: Pragmas specific to x86 targets.
*
****************************************************************************/
#include "cvars.h"
#include "cgswitch.h"
#include "pragdefn.h"
#include "pdefn2.h"
#include "asminlin.h"
local void GetParmInfo( void );
local void GetRetInfo( void );
local void GetSTRetInfo( void );
local void GetSaveInfo( void );
local int GetByteSeq( void );
extern TREEPTR CurFuncNode;
static int AsmFuncNum;
static hw_reg_set AsmRegsSaved = { HW_D( HW_FULL ) };
static hw_reg_set StackParms[] = { HW_D( HW_EMPTY ) };
#if _CPU == 386
static hw_reg_set OptlinkParms[] = { HW_D( HW_FLTS ),HW_D( HW_EMPTY )};
#endif
void PragmaInit()
{
call_class call_type;
int cpu;
int fpu;
int use32;
#if _CPU == 386
use32 = 1;
cpu = 3;
#else
use32 = 0;
cpu = 0;
#endif
AsmFuncNum = 0;
switch( GET_CPU( ProcRevision ) ) {
case CPU_86: cpu = 0; break;
case CPU_186: cpu = 1; break;
case CPU_286: cpu = 2; break;
case CPU_386: cpu = 3; break;
case CPU_486: cpu = 4; break;
case CPU_586: cpu = 5; break;
case CPU_686: cpu = 6; break;
}
switch( GET_FPU( ProcRevision ) ) {
case FPU_NONE: fpu = 0; break;
default: fpu = 1; break;
}
AsmInit( cpu, fpu, use32, 1 );
PragInit();
HeadLibs = NULL;
/* predefine "cdecl" and "pascal" pragmas 18-aug-90 */
call_type = ( DefaultInfo.class & FAR );
CdeclInfo.class = call_type |
CALLER_POPS |
NO_FLOAT_REG_RETURNS |
NO_STRUCT_REG_RETURNS |
ROUTINE_RETURN |
#if _CPU == 8086
LOAD_DS_ON_CALL |
#endif
SPECIAL_STRUCT_RETURN;
CdeclInfo.objname = CStrSave( "_*" );
CdeclInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
memcpy( CdeclInfo.parms, StackParms, sizeof( StackParms ) );
HW_CAsgn( CdeclInfo.returns, HW_EMPTY );
PascalInfo.class = call_type |
REVERSE_PARMS |
NO_FLOAT_REG_RETURNS |
NO_STRUCT_REG_RETURNS |
/* ROUTINE_RETURN | JFD Nov-15-91 */
SPECIAL_STRUCT_RETURN;
PascalInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
memcpy( PascalInfo.parms, StackParms, sizeof( StackParms ) );
PascalInfo.objname = CStrSave( "^" );
HW_CAsgn( PascalInfo.returns, HW_EMPTY );
FortranInfo.objname = CStrSave( "^" );
StdcallInfo.class = call_type |
// NO_FLOAT_REG_RETURNS | BBB - Jan-31-94
// NO_STRUCT_REG_RETURNS |
// ROUTINE_RETURN;
SPECIAL_STRUCT_RETURN;
StdcallInfo.objname = CStrSave( "_*" );
StdcallInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
memcpy( StdcallInfo.parms, StackParms, sizeof( StackParms ) );
HW_CAsgn( StdcallInfo.returns, HW_EMPTY );
OptlinkInfo.class = call_type |
CALLER_POPS |
#ifdef PARMS_STACK_RESERVE
PARMS_STACK_RESERVE |
#endif
NO_STRUCT_REG_RETURNS |
SPECIAL_STRUCT_RETURN;
OptlinkInfo.objname = CStrSave( "*" );
#if _CPU == 386
HW_CTurnOn( OptlinkParms[0], HW_EAX );
HW_CTurnOn( OptlinkParms[0], HW_ECX );
HW_CTurnOn( OptlinkParms[0], HW_EDX );
OptlinkInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( OptlinkParms ) );
memcpy( OptlinkInfo.parms, OptlinkParms, sizeof( OptlinkParms ) );
#else
OptlinkInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
memcpy( OptlinkInfo.parms, StackParms, sizeof( StackParms ) );
#endif
HW_CAsgn( OptlinkInfo.returns, HW_FLTS );
SyscallInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
memcpy( SyscallInfo.parms, StackParms, sizeof( StackParms ) );
SyscallInfo.objname = CStrSave( "*" );
SyscallInfo.class = CALLER_POPS |
NO_STRUCT_REG_RETURNS |
SPECIAL_STRUCT_RETURN;
#if _CPU == 386
HW_CAsgn( CdeclInfo.streturn, HW_EAX );
HW_CTurnOff( CdeclInfo.save, HW_EAX );
/* HW_CTurnOff( CdeclInfo.save, HW_EBX ); AFS Nov-21-94 */
HW_CTurnOff( CdeclInfo.save, HW_ECX );
HW_CTurnOff( CdeclInfo.save, HW_EDX );
/* HW_CAsgn( PascalInfo.streturn, HW_EAX ); JFD Nov-15-91 */
HW_CTurnOff( PascalInfo.save, HW_EAX );
HW_CTurnOff( PascalInfo.save, HW_EBX );
HW_CTurnOff( PascalInfo.save, HW_ECX );
HW_CTurnOff( PascalInfo.save, HW_EDX );
/* HW_CAsgn( StdcallInfo.streturn, HW_EAX ); BBB Jan-31-94 */
HW_CTurnOff( StdcallInfo.save, HW_EAX );
/* HW_CTurnOff( StdcallInfo.save, HW_EBX ); CGE Jan-25-93 */
HW_CTurnOff( StdcallInfo.save, HW_ECX );
HW_CTurnOff( StdcallInfo.save, HW_EDX );
HW_CTurnOff( SyscallInfo.save, HW_EAX );
HW_CTurnOn ( SyscallInfo.save, HW_EBX );
HW_CTurnOff( SyscallInfo.save, HW_ECX );
HW_CTurnOff( SyscallInfo.save, HW_EDX );
HW_CAsgn( SyscallInfo.streturn, HW_EMPTY );
HW_CAsgn( OptlinkInfo.streturn, HW_EMPTY );
HW_CTurnOff( OptlinkInfo.save, HW_EAX );
HW_CTurnOff( OptlinkInfo.save, HW_ECX );
HW_CTurnOff( OptlinkInfo.save, HW_EDX );
HW_CTurnOff( AsmRegsSaved, HW_EAX );
HW_CTurnOff( AsmRegsSaved, HW_EBX );
HW_CTurnOff( AsmRegsSaved, HW_ECX );
HW_CTurnOff( AsmRegsSaved, HW_EDX );
HW_CTurnOff( AsmRegsSaved, HW_ESI );
HW_CTurnOff( AsmRegsSaved, HW_EDI );
#else
HW_CAsgn( CdeclInfo.streturn, HW_AX );
HW_CTurnOff( CdeclInfo.save, HW_ABCD );
HW_CTurnOff( CdeclInfo.save, HW_ES );
HW_CTurnOff( PascalInfo.save, HW_ABCD );
HW_CTurnOff( PascalInfo.save, HW_ES );
HW_CAsgn( StdcallInfo.streturn, HW_AX );
HW_CTurnOff( StdcallInfo.save, HW_ABCD );
HW_CTurnOff( StdcallInfo.save, HW_ES );
/* roughly like pascal */
HW_CTurnOff( SyscallInfo.save, HW_ABCD );
HW_CTurnOff( SyscallInfo.save, HW_ES );
/* roughly like pascal */
HW_CTurnOff( OptlinkInfo.save, HW_ABCD );
HW_CTurnOff( OptlinkInfo.save, HW_ES );
HW_CTurnOff( AsmRegsSaved, HW_ABCD );
HW_CTurnOff( AsmRegsSaved, HW_SI );
HW_CTurnOff( AsmRegsSaved, HW_DI );
HW_CTurnOff( AsmRegsSaved, HW_ES );
#endif
#if _CPU == 386
{
/* these are internal, and will never be pointed to by
an aux_entry, so we don't have to worry about them
or their fields being freed */
static hw_reg_set STOSBParms[] = { HW_D( HW_EAX ),
HW_D( HW_EDX ),
HW_D( HW_ECX ),
HW_D( HW_EMPTY ) };
call_type = NO_FLOAT_REG_RETURNS | NO_STRUCT_REG_RETURNS
| SPECIAL_STRUCT_RETURN;
STOSBInfo = DefaultInfo;
STOSBInfo.class = call_type;
STOSBInfo.parms = STOSBParms;
STOSBInfo.objname = "*";
/*
* These are not freed when we shut down so we can't just point at the
* CdeclInfo parms etc. Do not call FreeInfo on these. BBB
*/
Far16CdeclInfo = CdeclInfo;
Far16CdeclInfo.class |= FAR16_CALL;
// __far16 __cdecl depends on EBX being trashed in __cdecl
// but NT 386 __cdecl preserves EBX
HW_CTurnOff( Far16CdeclInfo.save, HW_EBX );
Far16PascalInfo = PascalInfo;
Far16PascalInfo.class |= FAR16_CALL;
#if 0
Far16CdeclInfo = DefaultInfo;
Far16CdeclInfo.class = call_type | ROUTINE_RETURN | FAR16_CALL;
Far16CdeclInfo.objname = "_*";
Far16CdeclInfo.parms = CdeclInfo.parms; // BBB - March 23, 1994
Far16CdeclInfo.save = CdeclInfo.save; // BBB - March 23, 1994
Far16PascalInfo = DefaultInfo;
Far16PascalInfo.class = call_type | REVERSE_PARMS | FAR16_CALL;
Far16PascalInfo.objname = "^";
Far16PascalInfo.parms = PascalInfo.parms; // BBB - March 23, 1994
Far16PascalInfo.save = PascalInfo.save; // BBB - March 23, 1994
#endif
}
#endif
}
static int GetAliasInfo()
{
int isfar16;
auto char buff[256];
CurrAlias = &DefaultInfo;
if( CurToken != T_LEFT_PAREN ) return( 1 );
NextToken();
if( CurToken != T_ID ) return( 0 );
PragCurrAlias();
strcpy( buff, Buffer );
NextToken();
if( CurToken == T_RIGHT_PAREN ) {
NextToken();
return( 1 );
} else if( CurToken == T_COMMA ) {
NextToken();
if( CurToken != T_ID ) return( 0 );
isfar16 = PragRecog( "far16" );
CreateAux( buff );
PragCurrAlias();
NextToken();
if( CurToken == T_RIGHT_PAREN ) {
*CurrInfo = *CurrAlias;
NextToken();
}
if( isfar16 ) {
CurrInfo->flags |= AUX_FLAG_FAR16;
}
PragEnding();
return( 0 ); /* process no more! */
} else {
return( 0 ); // shut up the compiler
}
}
void PragAux()
{
struct {
unsigned f_call : 1;
unsigned f_loadds : 1;
unsigned f_export : 1;
unsigned f_parm : 1;
unsigned f_value : 1;
unsigned f_modify : 1;
unsigned f_frame : 1;
unsigned uses_auto: 1;
} have;
if( !GetAliasInfo() ) return;
CurrEntry = NULL;
if( CurToken != T_ID ) return;
SetCurrInfo();
NextToken();
*CurrInfo = *CurrAlias;
PragObjNameInfo();
have.f_call = 0;
have.f_loadds = 0;
have.f_export = 0;
have.f_parm = 0;
have.f_value = 0;
have.f_modify = 0;
have.f_frame = 0;
have.uses_auto = 0; /* BBB - Jan 26, 1994 */
for( ;; ) {
if( !have.f_call && CurToken == T_EQUAL ) {
have.uses_auto = GetByteSeq();
have.f_call = 1;
} else if( !have.f_call && PragRecog( "far" ) ) {
CurrInfo->class |= FAR;
have.f_call = 1;
} else if( !have.f_call && PragRecog( "near" ) ) {
CurrInfo->class &= ~FAR;
have.f_call = 1;
} else if( !have.f_loadds && PragRecog( "loadds" ) ) {
CurrInfo->class |= LOAD_DS_ON_ENTRY;
have.f_loadds = 1;
} else if( !have.f_export && PragRecog( "export" ) ) {
CurrInfo->class |= DLL_EXPORT;
have.f_export = 1;
} else if( !have.f_parm && PragRecog( "parm" ) ) {
GetParmInfo();
have.f_parm = 1;
} else if( !have.f_value && PragRecog( "value" ) ) {
GetRetInfo();
have.f_value = 1;
} else if( !have.f_value && PragRecog( "aborts" ) ) {
CurrInfo->class |= SUICIDAL;
have.f_value = 1;
} else if( !have.f_modify && PragRecog( "modify" ) ) {
GetSaveInfo();
have.f_modify = 1;
} else if( !have.f_frame && PragRecog( "frame" ) ) {
CurrInfo->class |= GENERATE_STACK_FRAME;
have.f_frame = 1;
} else {
break;
}
}
if( have.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 );
}
PragEnding();
}
typedef enum {
FIXWORD_NONE,
FIXWORD_FLOAT,
FIXWORD_SEGMENT,
FIXWORD_OFFSET,
FIXWORD_RELOFF
} fix_words;
local fix_words FixupKeyword()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -