static void pragmaAuxInfoInit( void ) /***********************************/ { #if _CPU == 386 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_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 */ STOSBInfo = WatcallInfo; STOSBInfo.cclass = NO_FLOAT_REG_RETURNS | NO_STRUCT_REG_RETURNS | SPECIAL_STRUCT_RETURN; STOSBInfo.parms = STOSBParms; STOSBInfo.objname = "*"; #endif }
void SetAuxStackConventions( void ) /*********************************/ { WatcallInfo.cclass &= ( GENERATE_STACK_FRAME | FAR_CALL ); WatcallInfo.cclass |= CALLER_POPS | NO_8087_RETURNS; WatcallInfo.parms = metaWareParms; HW_CTurnOff( WatcallInfo.save, HW_EAX ); HW_CTurnOff( WatcallInfo.save, HW_EDX ); HW_CTurnOff( WatcallInfo.save, HW_ECX ); HW_CTurnOff( WatcallInfo.save, HW_FLTS ); WatcallInfo.objname = AUX_STRALLOC( "*" ); }
static void GetRetInfo( void ) /***************************/ { struct { bool f_no8087 : 1; bool f_list : 1; bool f_struct : 1; } have; have.f_no8087 = false; have.f_list = false; have.f_struct = false; AuxInfo.cclass &= ~ NO_8087_RETURNS; AuxInfoFlg.f_8087_returns = true; for( ;; ) { if( !have.f_no8087 && PragRecog( "no8087" ) ) { have.f_no8087 = true; HW_CTurnOff( AuxInfo.returns, HW_FLTS ); AuxInfo.cclass |= NO_8087_RETURNS; } else if( !have.f_list && PragRegSet() != T_NULL ) { have.f_list = true; AuxInfo.cclass |= SPECIAL_RETURN; AuxInfo.returns = PragRegList(); } else if( !have.f_struct && PragRecog( "struct" ) ) { have.f_struct = true; GetSTRetInfo(); } 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; AuxInfo.cclass &= ~ NO_8087_RETURNS; /* 29-mar-90 */ AuxInfoFlg.f_8087_returns = 1; for( ;; ) { if( !have.f_no8087 && PragRecog( "no8087" ) ) { have.f_no8087 = 1; HW_CTurnOff( AuxInfo.returns, HW_FLTS ); AuxInfo.cclass |= NO_8087_RETURNS; } else if( !have.f_list && PragRegSet() != T_NULL ) { have.f_list = 1; AuxInfo.cclass |= SPECIAL_RETURN; AuxInfo.returns = PragRegList(); } else if( !have.f_struct && PragRecog( "struct" ) ) { have.f_struct = 1; GetSTRetInfo(); } else { break; } } }
static 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->cclass &= ~ NO_8087_RETURNS; for( ;; ) { if( !have.f_no8087 && PragRecog( "no8087" ) ) { have.f_no8087 = 1; HW_CTurnOff( CurrInfo->returns, HW_FLTS ); CurrInfo->cclass |= NO_8087_RETURNS; } else if( !have.f_list && IS_REGSET( CurToken ) ) { have.f_list = 1; CurrInfo->cclass |= SPECIAL_RETURN; CurrInfo->returns = PragRegList(); } else if( !have.f_struct && PragRecog( "struct" ) ) { have.f_struct = 1; GetSTRetInfo(); } else { break; } } }
hw_reg_set MustSaveRegs( void ) /**********************************/ { hw_reg_set save; hw_reg_set tmp; HW_CAsgn( save, HW_FULL ); HW_TurnOff( save, CurrProc->state.modify ); HW_CTurnOff( save, HW_UNUSED ); if( CurrProc->state.attr & ROUTINE_MODIFY_EXACT ) { HW_TurnOff( save, CurrProc->state.return_reg ); } else { tmp = CurrProc->state.parm.used; HW_TurnOn( tmp, CurrProc->state.return_reg ); tmp = FullReg( tmp ); HW_TurnOff( save, tmp ); } tmp = StackReg(); HW_TurnOff( save, tmp ); if( HW_CEqual( CurrProc->state.return_reg, HW_EMPTY ) ) { tmp = ReturnReg( WD, _NPX( CurrProc->state.attr ) ); HW_TurnOff( save, tmp ); } tmp = CurrProc->state.unalterable; HW_TurnOff( tmp, DisplayReg() ); HW_TurnOff( tmp, StackReg() ); HW_TurnOff( save, tmp ); return( save ); }
type_class_def CallState( aux_handle aux, type_def *tipe, call_state *state ) /****************************************************************************/ { type_class_def class; uint i; hw_reg_set parms[24]; hw_reg_set *parm_src; hw_reg_set *parm_dst; state->unalterable = FixedRegs(); HW_CAsgn( state->modify, HW_FULL ); HW_TurnOff( state->modify, SavedRegs() ); HW_CTurnOff( state->modify, HW_UNUSED ); state->used = state->modify; /* anything not saved is used*/ state->attr = 0; i = 0; parm_src = ParmRegs(); parm_dst = &parms[0]; for(;;) { *parm_dst = *parm_src; if( HW_CEqual( *parm_dst, HW_EMPTY ) ) break; if( HW_Ovlap( *parm_dst, state->unalterable ) ) { FEMessage( MSG_BAD_SAVE, aux ); } HW_CTurnOff( *parm_dst, HW_UNUSED ); parm_dst++; parm_src++; i++; } i++; state->parm.table = CGAlloc( i*sizeof( hw_reg_set ) ); Copy( parms, state->parm.table, i * sizeof( hw_reg_set ) ); HW_CAsgn( state->parm.used, HW_EMPTY ); state->parm.curr_entry = state->parm.table; state->parm.offset = 0; InitPPCParmState( state ); class = ReturnClass( tipe, state->attr ); if( *(call_class *)FEAuxInfo( aux, CALL_CLASS ) & HAS_VARARGS ) { state->attr |= ROUTINE_HAS_VARARGS; } UpdateReturn( state, tipe, class, aux ); return( class ); }
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(); }
static void miscAnalysis( OPT_STORAGE *data ) { #if _CPU == 8086 if( data->bd || data->zu ) { if( TargetSwitches & SMART_WINDOWS ) { CErr1( ERR_ZWS_MUST_HAVE_SS_DS_SAME ); } } #endif if( GET_CPU( CpuSwitches ) < CPU_386 ) { /* issue warning message if /zf[f|p] or /zg[f|p] spec'd? */ TargetSwitches &= ~( FLOATING_FS | FLOATING_GS ); } if( ! CompFlags.save_restore_segregs ) { if( TargetSwitches & FLOATING_DS ) { HW_CTurnOff( WatcallInfo.save, HW_DS ); } if( TargetSwitches & FLOATING_ES ) { HW_CTurnOff( WatcallInfo.save, HW_ES ); } if( TargetSwitches & FLOATING_FS ) { HW_CTurnOff( WatcallInfo.save, HW_FS ); } if( TargetSwitches & FLOATING_GS ) { HW_CTurnOff( WatcallInfo.save, HW_GS ); } } if( GET_FPU( CpuSwitches ) > FPU_NONE ) { PreDefineStringMacro( "__FPI__" ); } #if _CPU == 386 if( ! CompFlags.register_conventions ) { SetAuxStackConventions(); } #endif if( data->zx ) { HW_CTurnOff( WatcallInfo.save, HW_FLTS ); } }
static void pragmaInit( // INITIALIZATION FOR PRAGMAS INITFINI* defn ) // - definition { defn = defn; PragInit(); PragmaAuxInfoInit( CompFlags.use_stdcall_at_number ); #if _CPU == 386 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_CTurnOff( asmRegsSaved, HW_ABCD ); HW_CTurnOff( asmRegsSaved, HW_SI ); HW_CTurnOff( asmRegsSaved, HW_DI ); HW_CTurnOff( asmRegsSaved, HW_ES ); #endif SetAuxDefaultInfo(); }
static byte Displacement( signed_32 val, hw_reg_set regs ) /************************************************************/ { HW_CTurnOff( regs, HW_SEGS ); if( val == 0 && !HW_CEqual( regs, HW_BP ) ) return( D0 ); if( val <= 127 && val >= -128 ) { AddByte( val & 0xff ); return( D8 ); } else { val &= 0xffff; AddByte( val ); AddByte( val >> 8 ); return( D16 ); } }
void UpdateReturn( call_state *state, type_def *tipe, type_class_def type_class, aux_handle aux ) /**************************************************************************************************/ { hw_reg_set normal; if( _FPULevel( FPU_87 ) && _NPX( state->attr ) && (tipe->attr & TYPE_FLOAT) ) { HW_COnlyOn( state->return_reg, HW_ST0 ); } else { HW_CTurnOff( state->return_reg, HW_FLTS ); } if( tipe == TypeNone ) { if( HW_CEqual( state->return_reg, HW_EMPTY ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); HW_CAsgn( state->return_reg, HW_EMPTY ); state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } else if( type_class == XX ) { normal = ReturnReg( WD, _NPX( state->attr ) ); if( HW_Equal( state->return_reg, normal ) ) return; if( HW_CEqual( state->return_reg, HW_EMPTY ) ) return; // if( !HW_Ovlap( state->return_reg, state->unalterable ) && // IsRegClass( state->return_reg, WD ) ) // return; if( IsRegClass( state->return_reg, WD ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); state->return_reg = normal; state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } else { normal = ReturnReg( type_class, _NPX( state->attr ) ); if( HW_Equal( state->return_reg, normal ) ) return; // if( !HW_Ovlap( state->return_reg, state->unalterable ) && // IsRegClass( state->return_reg, type_class ) ) // return; if( IsRegClass( state->return_reg, type_class ) ) return; FEMessage( MSG_BAD_RETURN_REGISTER, aux ); state->return_reg = normal; state->attr &= ~ROUTINE_HAS_SPECIAL_RETURN; } }
void AsmSysMakeInlineAsmFunc( bool too_many_bytes ) /*************************************************/ { int code_length; SYM_HANDLE sym_handle; TREEPTR tree; bool uses_auto; char name[8]; /* unused parameters */ (void)too_many_bytes; code_length = AsmCodeAddress; if( code_length != 0 ) { sprintf( name, "F.%d", AsmFuncNum ); ++AsmFuncNum; CreateAux( name ); CurrInfo = (aux_info *)CMemAlloc( sizeof( aux_info ) ); *CurrInfo = WatcallInfo; CurrInfo->use = 1; CurrInfo->save = AsmRegsSaved; // indicate no registers saved uses_auto = InsertFixups( AsmCodeBuffer, code_length, &CurrInfo->code ); 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( name, FuncNode( GetType( TYPE_VOID ), FLAG_NONE, NULL ) ); tree = LeafNode( OPR_FUNCNAME ); tree->op.u2.sym_handle = sym_handle; tree = ExprNode( tree, OPR_CALL, NULL ); tree->u.expr_type = GetType( TYPE_VOID ); AddStmt( tree ); } }
extern type_class_def CallState( aux_handle aux, type_def *tipe, call_state *state ) /*******************************************************************/ { type_class_def class; uint i; hw_reg_set parms[20]; hw_reg_set *parm_src; hw_reg_set *parm_dst; hw_reg_set *pregs; call_class cclass; call_class *pcclass; risc_byte_seq *code; bool have_aux_code = FALSE; state->unalterable = FixedRegs(); if( FEAttr( AskForLblSym( CurrProc->label ) ) & FE_VARARGS ) { HW_TurnOn( state->unalterable, VarargsHomePtr() ); } // For code bursts only, query the #pragma aux instead of using // hardcoded calling convention. If it ever turns out that we need // to support more than a single calling convention, this will need // to change to work more like x86 if( !AskIfRTLabel( CurrProc->label ) ) { code = FEAuxInfo( aux, CALL_BYTES ); if( code != NULL ) { have_aux_code = TRUE; } } pregs = FEAuxInfo( aux, SAVE_REGS ); HW_CAsgn( state->modify, HW_FULL ); if( have_aux_code ) { HW_TurnOff( state->modify, *pregs ); } else { HW_TurnOff( state->modify, SavedRegs() ); } HW_CTurnOff( state->modify, HW_UNUSED ); state->used = state->modify; /* anything not saved is used */ state->attr = 0; pcclass = FEAuxInfo( aux, CALL_CLASS ); cclass = *pcclass; if( cclass & SETJMP_KLUGE ) { state->attr |= ROUTINE_IS_SETJMP; } if( cclass & SUICIDAL ) { state->attr |= ROUTINE_NEVER_RETURNS; } if( cclass & NO_MEMORY_CHANGED ) { state->attr |= ROUTINE_MODIFIES_NO_MEMORY; } if( cclass & NO_MEMORY_READ ) { state->attr |= ROUTINE_READS_NO_MEMORY; } i = 0; if( have_aux_code ) { parm_src = FEAuxInfo( aux, PARM_REGS ); } else { parm_src = ParmRegs(); } parm_dst = &parms[0]; for( ;; ) { *parm_dst = *parm_src; if( HW_CEqual( *parm_dst, HW_EMPTY ) ) break; if( HW_Ovlap( *parm_dst, state->unalterable ) ) { FEMessage( MSG_BAD_SAVE, aux ); } HW_CTurnOff( *parm_dst, HW_UNUSED ); parm_dst++; parm_src++; i++; } i++; state->parm.table = CGAlloc( i * sizeof( hw_reg_set ) ); Copy( parms, state->parm.table, i * sizeof( hw_reg_set ) ); HW_CAsgn( state->parm.used, HW_EMPTY ); state->parm.curr_entry = state->parm.table; state->parm.offset = 0; class = ReturnClass( tipe, state->attr ); UpdateReturn( state, tipe, class, aux ); return( class ); }
instruction *rMAKECALL( instruction *ins ) /********************************************* Using the table RTInfo[], do all the necessary stuff to turn instruction "ins" into a call to a runtime support routine. Move the parms into registers, and move the return register of the runtime routine into the result. Used for 386 and 370 versions */ { rtn_info *info; label_handle lbl; instruction *left_ins; instruction *new_ins; instruction *last_ins; name *reg_name; hw_reg_set regs; hw_reg_set all_regs; hw_reg_set tmp; rt_class rtindex; if( !_IsConvert( ins ) ) { rtindex = LookupRoutine( ins ); } else { /* look it up again in case we ran out of memory during expansion*/ rtindex = LookupConvertRoutine( ins ); } info = &RTInfo[rtindex]; regs = _ParmReg( info->left ); all_regs = regs; left_ins = MakeMove( ins->operands[0], AllocRegName( regs ), info->operand_class ); ins->operands[0] = left_ins->result; MoveSegOp( ins, left_ins, 0 ); PrefixIns( ins, left_ins ); regs = _ParmReg( info->right ); if( !HW_CEqual( regs, HW_EMPTY ) ) { new_ins = MakeMove( ins->operands[1], AllocRegName( regs ), info->operand_class ); ins->operands[1] = new_ins->result; MoveSegOp( ins, new_ins, 0 ); HW_TurnOn( all_regs, regs ); PrefixIns( ins, new_ins ); } #if _TARGET & _TARG_370 tmp = RAReg(); HW_TurnOn( all_regs, tmp ); tmp = LNReg(); HW_TurnOn( all_regs, tmp ); #elif _TARGET & _TARG_80386 { tmp = ReturnReg( WD, false ); HW_TurnOn( all_regs, tmp ); } #endif reg_name = AllocRegName( all_regs ); lbl = RTLabel( rtindex ); new_ins = NewIns( 3 ); new_ins->head.opcode = OP_CALL; new_ins->type_class = ins->type_class; new_ins->operands[CALL_OP_USED] = reg_name; new_ins->operands[CALL_OP_USED2] = reg_name; new_ins->operands[CALL_OP_ADDR] = AllocMemory( lbl, 0, CG_LBL, ins->type_class ); new_ins->result = NULL; new_ins->num_operands = 2; /* special case for OP_CALL*/ #if _TARGET & _TARG_AXP { HW_CTurnOn( all_regs, HW_FULL ); HW_TurnOff( all_regs, SavedRegs() ); HW_CTurnOff( all_regs, HW_UNUSED ); HW_TurnOn( all_regs, ReturnAddrReg() ); } #endif new_ins->zap = (register_name *)AllocRegName( all_regs ); /* all parm regs could be zapped*/ last_ins = new_ins; if( ins->result == NULL || _OpIsCondition( ins->head.opcode ) ) { /* comparison, still need conditional jumps*/ ins->operands[0] = AllocIntConst( 0 ); ins->operands[1] = AllocIntConst( 1 ); DelSeg( ins ); DoNothing( ins ); /* just conditional jumps for ins*/ PrefixIns( ins, new_ins ); new_ins->ins_flags |= INS_CC_USED; last_ins = ins; } else { regs = _ParmReg( info->result ); tmp = regs; HW_TurnOn( tmp, new_ins->zap->reg ); new_ins->zap = (register_name *)AllocRegName( tmp ); reg_name = AllocRegName( regs ); new_ins->result = reg_name; last_ins = MakeMove( reg_name, ins->result, ins->type_class ); ins->result = last_ins->operands[0]; MoveSegRes( ins, last_ins ); SuffixIns( ins, last_ins ); ReplIns( ins, new_ins ); } FixCallIns( new_ins ); UpdateLive( left_ins, last_ins ); return( left_ins ); }
extern void DumpOperand( name *operand ) { /********************************************/ char buffer[20]; hw_reg_set reg; name *base; if( operand->n.class == N_INDEXED ) { if( operand->i.base != NULL ) { if( !( operand->i.index_flags & X_FAKE_BASE ) ) { if( operand->i.index_flags & X_LOW_ADDR_BASE ) { DumpLiteral( "l^" ); } DumpOperand( operand->i.base ); if( operand->i.constant > 0 ) { DumpChar( '+' ); } } } if( operand->i.constant != 0 ) { DumpLong( operand->i.constant ); } DumpChar( '[' ); if( operand->i.index_flags & X_BASE ) { reg = operand->i.index->r.reg; #if _TARGET & ( _TARG_IAPX86 | _TARG_80386 ) if( HW_COvlap( reg, HW_SEGS ) ) { hw_reg_set tmp; tmp = reg; HW_COnlyOn( tmp, HW_SEGS ); DumpRegName( tmp ); DumpChar( ':' ); HW_CTurnOff( reg, HW_SEGS ); } #endif if( operand->i.index_flags & X_HIGH_BASE ) { DumpRegName( HighReg( reg ) ); DumpChar( '+' ); DumpRegName( LowReg( reg ) ); } else { DumpRegName( LowReg( reg ) ); DumpChar( '+' ); DumpRegName( HighReg( reg ) ); } } else { DumpOperand( operand->i.index ); } if( operand->i.scale != 0 ) { DumpChar( '*' ); DumpInt( 1 << operand->i.scale ); } if( operand->i.index_flags & ( X_ALIGNED_1 | X_ALIGNED_2 | X_ALIGNED_4 | X_ALIGNED_8 ) ) { DumpChar( '$' ); DumpInt( FlagsToAlignment( operand->i.index_flags ) ); } DumpChar( ']' ); base = operand->i.base; if( base != NULL ) { if( operand->i.index_flags & X_FAKE_BASE ) { DumpChar( '{' ); if( base->n.class == N_MEMORY ) { DumpXString( AskName(base->v.symbol, base->m.memory_type) ); } else if( base->n.class == N_TEMP ) { if( _FrontEndTmp( base ) ) { DumpXString( FEName( base->v.symbol ) ); } else { DumpOperand( base ); } } DumpChar( '}' ); } }
type_class_def CallState( aux_handle aux, type_def *tipe, call_state *state ) /****************************************************************************/ { call_class cclass; type_class_def type_class; uint i; hw_reg_set parms[10]; hw_reg_set *parm_src; hw_reg_set *parm_dst; hw_reg_set *pregs; hw_reg_set tmp; state->unalterable = FixedRegs(); pregs = FEAuxInfo( aux, SAVE_REGS ); HW_CAsgn( state->modify, HW_FULL ); HW_TurnOff( state->modify, *pregs ); HW_CTurnOff( state->modify, HW_UNUSED ); state->used = state->modify; /* anything not saved is used*/ tmp = state->used; HW_TurnOff( tmp, StackReg() ); HW_CTurnOff( tmp, HW_BP ); // should be able to call routine which modifies BP if( HW_Ovlap( state->unalterable, tmp ) ) { FEMessage( MSG_BAD_SAVE, aux ); } state->attr = ROUTINE_REMOVES_PARMS; cclass = *(call_class *)FEAuxInfo( aux, CALL_CLASS ); if( cclass & INTERRUPT ) { state->attr |= ROUTINE_INTERRUPT; } else if( cclass & FAR_CALL ) { state->attr |= ROUTINE_LONG; } else if( cclass & FAR16_CALL ) { state->attr |= ROUTINE_FAR16; } if( cclass & CALLER_POPS ) { state->attr &= ~ROUTINE_REMOVES_PARMS; } if( cclass & SUICIDAL ) { state->attr |= ROUTINE_NEVER_RETURNS; } if( cclass & ROUTINE_RETURN ) { state->attr |= ROUTINE_ALLOCS_RETURN; } if( cclass & NO_STRUCT_REG_RETURNS ) { state->attr |= ROUTINE_NO_STRUCT_REG_RETURNS; } if( cclass & NO_FLOAT_REG_RETURNS ) { state->attr |= ROUTINE_NO_FLOAT_REG_RETURNS; state->attr |= ROUTINE_NO_8087_RETURNS; } if( cclass & NO_8087_RETURNS ) { state->attr |= ROUTINE_NO_8087_RETURNS; } if( cclass & MODIFY_EXACT ) { state->attr |= ROUTINE_MODIFY_EXACT; } if( cclass & NO_MEMORY_CHANGED ) { state->attr |= ROUTINE_MODIFIES_NO_MEMORY; } if( cclass & NO_MEMORY_READ ) { state->attr |= ROUTINE_READS_NO_MEMORY; } if( cclass & LOAD_DS_ON_ENTRY ) { state->attr |= ROUTINE_LOADS_DS; } if( cclass & LOAD_DS_ON_CALL ) { state->attr |= ROUTINE_NEEDS_DS_LOADED; } if( cclass & PARMS_STACK_RESERVE ) { state->attr |= ROUTINE_STACK_RESERVE; } if( cclass & PARMS_PREFER_REGS ) { state->attr |= ROUTINE_PREFER_REGS; } if( cclass & FARSS ) { state->attr |= ROUTINE_FARSS; } if( state == &CurrProc->state ) { if( cclass & ( GENERATE_STACK_FRAME | PROLOG_HOOKS | EPILOG_HOOKS ) ) { CurrProc->prolog_state |= GENERATE_FAT_PROLOG; state->attr |= ROUTINE_NEEDS_PROLOG; } if( cclass & PROLOG_HOOKS ) { CurrProc->prolog_state |= GENERATE_PROLOG_HOOKS; } if( cclass & EPILOG_HOOKS ) { CurrProc->prolog_state |= GENERATE_EPILOG_HOOKS; } if( cclass & FAT_WINDOWS_PROLOG ) { CurrProc->prolog_state |= GENERATE_FAT_PROLOG; } if( cclass & EMIT_FUNCTION_NAME ) { CurrProc->prolog_state |= GENERATE_FUNCTION_NAME; } if( cclass & THUNK_PROLOG ) { CurrProc->prolog_state |= GENERATE_THUNK_PROLOG; } if( cclass & GROW_STACK ) { CurrProc->prolog_state |= GENERATE_GROW_STACK; } if( cclass & TOUCH_STACK ) { CurrProc->prolog_state |= GENERATE_TOUCH_STACK; } if( cclass & LOAD_RDOSDEV_ON_ENTRY ) { CurrProc->prolog_state |= GENERATE_RDOSDEV_PROLOG; } } type_class = ReturnClass( tipe, state->attr ); i = 0; parm_dst = &parms[0]; for( parm_src = FEAuxInfo( aux, PARM_REGS ); !HW_CEqual( *parm_src, HW_EMPTY ); ++parm_src ) { *parm_dst = *parm_src; if( HW_Ovlap( *parm_dst, state->unalterable ) ) { FEMessage( MSG_BAD_SAVE, aux ); } HW_CTurnOff( *parm_dst, HW_UNUSED ); parm_dst++; i++; } *parm_dst = *parm_src; i++; state->parm.table = CGAlloc( i*sizeof( hw_reg_set ) ); Copy( parms, state->parm.table, i * sizeof( hw_reg_set ) ); HW_CAsgn( state->parm.used, HW_EMPTY ); state->parm.curr_entry = state->parm.table; state->parm.offset = 0; if( tipe == TypeNone ) { HW_CAsgn( state->return_reg, HW_EMPTY ); } else if( type_class == XX ) { if( cclass & SPECIAL_STRUCT_RETURN ) { pregs = FEAuxInfo( aux, STRETURN_REG ); state->return_reg = *pregs; state->attr |= ROUTINE_HAS_SPECIAL_RETURN; } else { state->return_reg = StructReg(); } if( (state->attr & ROUTINE_ALLOCS_RETURN) == 0 ) { tmp = ReturnReg( WD, false ); HW_TurnOn( state->modify, tmp ); } } else { if( cclass & SPECIAL_RETURN ) { pregs = FEAuxInfo( aux, RETURN_REG ); state->return_reg = *pregs; state->attr |= ROUTINE_HAS_SPECIAL_RETURN; } else { state->return_reg = ReturnReg( type_class, _NPX( state->attr ) ); } } UpdateReturn( state, tipe, type_class, aux ); return( type_class ); }
void PragmaAuxInfoInit( int flag_stdatnum ) /*****************************************/ { hw_reg_set full_no_segs; call_class call_type; HW_CAsgn( full_no_segs, HW_FULL ); HW_CTurnOff( full_no_segs, HW_SEGS ); call_type = WatcallInfo.cclass & FAR_CALL; /************************************************* * __fortran calling convention *************************************************/ FortranInfo.objname = AUX_STRALLOC( "^" ); /************************************************* * __cdecl calling convention *************************************************/ CdeclInfo.cclass = call_type | #if _CPU == 8086 LOAD_DS_ON_CALL | #endif //REVERSE_PARMS | CALLER_POPS | //GENERATE_STACK_FRAME | #if _CPU == 8086 NO_FLOAT_REG_RETURNS | #endif NO_STRUCT_REG_RETURNS | ROUTINE_RETURN | //NO_8087_RETURNS | //SPECIAL_RETURN | SPECIAL_STRUCT_RETURN; CdeclInfo.parms = StackParms; CdeclInfo.objname = AUX_STRALLOC( "_*" ); HW_CAsgn( CdeclInfo.returns, HW_EMPTY ); HW_CAsgn( CdeclInfo.streturn, HW_EMPTY ); HW_TurnOn( CdeclInfo.save, full_no_segs ); HW_CTurnOff( CdeclInfo.save, HW_FLTS ); #if _CPU == 386 HW_CAsgn( CdeclInfo.streturn, HW_EAX ); HW_CTurnOff( CdeclInfo.save, HW_EAX ); // HW_CTurnOff( CdeclInfo.save, HW_EBX ); HW_CTurnOff( CdeclInfo.save, HW_ECX ); HW_CTurnOff( CdeclInfo.save, HW_EDX ); #else HW_CAsgn( CdeclInfo.streturn, HW_AX ); HW_CTurnOff( CdeclInfo.save, HW_ABCD ); HW_CTurnOff( CdeclInfo.save, HW_ES ); #endif /************************************************* * __pascal calling convention *************************************************/ PascalInfo.cclass = call_type | REVERSE_PARMS | //CALLER_POPS | //GENERATE_STACK_FRAME | NO_FLOAT_REG_RETURNS | NO_STRUCT_REG_RETURNS | //ROUTINE_RETURN | //NO_8087_RETURNS | //SPECIAL_RETURN | SPECIAL_STRUCT_RETURN; PascalInfo.parms = StackParms; PascalInfo.objname = AUX_STRALLOC( "^" ); HW_CAsgn( PascalInfo.returns, HW_EMPTY ); HW_CAsgn( PascalInfo.streturn, HW_EMPTY ); HW_TurnOn( PascalInfo.save, full_no_segs ); HW_CTurnOff( PascalInfo.save, HW_FLTS ); #if _CPU == 386 HW_CTurnOff( PascalInfo.save, HW_EAX ); HW_CTurnOff( PascalInfo.save, HW_EBX ); HW_CTurnOff( PascalInfo.save, HW_ECX ); HW_CTurnOff( PascalInfo.save, HW_EDX ); #else HW_CTurnOff( PascalInfo.save, HW_ABCD ); HW_CTurnOff( PascalInfo.save, HW_ES ); #endif /************************************************* * __stdcall calling convention *************************************************/ StdcallInfo.cclass = call_type | //REVERSE_PARMS | //CALLER_POPS | //GENERATE_STACK_FRAME | //NO_FLOAT_REG_RETURNS | //NO_STRUCT_REG_RETURNS | //ROUTINE_RETURN | //NO_8087_RETURNS | //SPECIAL_RETURN | SPECIAL_STRUCT_RETURN; StdcallInfo.parms = StackParms; #if _CPU == 386 if( flag_stdatnum ) { StdcallInfo.objname = AUX_STRALLOC( "_*#" ); } else { StdcallInfo.objname = AUX_STRALLOC( "_*" ); } #else flag_stdatnum = flag_stdatnum; StdcallInfo.objname = AUX_STRALLOC( "_*" ); #endif HW_CAsgn( StdcallInfo.returns, HW_EMPTY ); HW_CAsgn( StdcallInfo.streturn, HW_EMPTY ); HW_TurnOn( StdcallInfo.save, full_no_segs ); HW_CTurnOff( StdcallInfo.save, HW_FLTS ); #if _CPU == 386 // HW_CAsgn( StdcallInfo.streturn, HW_EAX ); HW_CTurnOff( StdcallInfo.save, HW_EAX ); // HW_CTurnOff( StdcallInfo.save, HW_EBX ); HW_CTurnOff( StdcallInfo.save, HW_ECX ); HW_CTurnOff( StdcallInfo.save, HW_EDX ); #else HW_CAsgn( StdcallInfo.streturn, HW_AX ); HW_CTurnOff( StdcallInfo.save, HW_ABCD ); HW_CTurnOff( StdcallInfo.save, HW_ES ); #endif /************************************************* * __fastcall calling convention *************************************************/ #if _CPU == 386 FastcallInfo.cclass = call_type | //REVERSE_PARMS | //CALLER_POPS | //GENERATE_STACK_FRAME | //NO_FLOAT_REG_RETURNS | //NO_STRUCT_REG_RETURNS | //ROUTINE_RETURN | //NO_8087_RETURNS | //SPECIAL_RETURN | SPECIAL_STRUCT_RETURN; FastcallInfo.parms = FastcallParms; FastcallInfo.objname = AUX_STRALLOC( "@*#" ); HW_CAsgn( FastcallInfo.returns, HW_EMPTY ); HW_CAsgn( FastcallInfo.streturn, HW_EMPTY ); HW_TurnOn( FastcallInfo.save, full_no_segs ); HW_CTurnOff( FastcallInfo.save, HW_FLTS ); HW_CTurnOff( FastcallInfo.save, HW_EAX ); // HW_CTurnOff( FastcallInfo.save, HW_EBX ); HW_CTurnOff( FastcallInfo.save, HW_ECX ); HW_CTurnOff( FastcallInfo.save, HW_EDX ); #else FastcallInfo.cclass = call_type | PARMS_PREFER_REGS | //REVERSE_PARMS | //CALLER_POPS | //GENERATE_STACK_FRAME | //NO_FLOAT_REG_RETURNS | //NO_STRUCT_REG_RETURNS | //ROUTINE_RETURN | //NO_8087_RETURNS | //SPECIAL_RETURN | SPECIAL_STRUCT_RETURN; FastcallInfo.parms = FastcallParms; FastcallInfo.objname = AUX_STRALLOC( "@*" ); HW_CAsgn( FastcallInfo.returns, HW_EMPTY ); HW_CAsgn( FastcallInfo.streturn, HW_EMPTY ); HW_TurnOn( FastcallInfo.save, full_no_segs ); HW_CTurnOff( FastcallInfo.save, HW_FLTS ); HW_CTurnOff( FastcallInfo.save, HW_ABCD ); HW_CTurnOff( FastcallInfo.save, HW_ES ); #endif /************************************************* * _Optlink calling convention *************************************************/ OptlinkInfo.cclass = call_type | #ifdef PARMS_STACK_RESERVE PARMS_STACK_RESERVE | #endif //REVERSE_PARMS | CALLER_POPS | //GENERATE_STACK_FRAME | //NO_FLOAT_REG_RETURNS | NO_STRUCT_REG_RETURNS | //ROUTINE_RETURN | //NO_8087_RETURNS | //SPECIAL_RETURN | SPECIAL_STRUCT_RETURN; #if _CPU == 386 OptlinkInfo.parms = OptlinkParms; #else OptlinkInfo.parms = StackParms; #endif OptlinkInfo.objname = AUX_STRALLOC( "*" ); HW_CAsgn( OptlinkInfo.returns, HW_EMPTY ); // HW_CAsgn( OptlinkInfo.returns, HW_FLTS ); HW_CAsgn( OptlinkInfo.streturn, HW_EMPTY ); HW_TurnOn( OptlinkInfo.save, full_no_segs ); HW_CTurnOff( OptlinkInfo.save, HW_FLTS ); #if _CPU == 386 HW_CTurnOff( OptlinkInfo.save, HW_EAX ); // HW_CTurnOff( OptlinkInfo.save, HW_EBX ); HW_CTurnOff( OptlinkInfo.save, HW_ECX ); HW_CTurnOff( OptlinkInfo.save, HW_EDX ); #else HW_CTurnOff( OptlinkInfo.save, HW_ABCD ); HW_CTurnOff( OptlinkInfo.save, HW_ES ); #endif /************************************************* * __syscall calling convention *************************************************/ SyscallInfo.cclass = call_type | //REVERSE_PARMS | CALLER_POPS | //GENERATE_STACK_FRAME | //NO_FLOAT_REG_RETURNS | NO_STRUCT_REG_RETURNS | //ROUTINE_RETURN | //NO_8087_RETURNS | //SPECIAL_RETURN | SPECIAL_STRUCT_RETURN; SyscallInfo.parms = StackParms; SyscallInfo.objname = AUX_STRALLOC( "*" ); HW_CAsgn( SyscallInfo.returns, HW_EMPTY ); HW_CAsgn( SyscallInfo.streturn, HW_EMPTY ); HW_TurnOn( SyscallInfo.save, full_no_segs ); HW_CTurnOff( SyscallInfo.save, HW_FLTS ); #if _CPU == 386 HW_CTurnOff( SyscallInfo.save, HW_EAX ); // HW_CTurnOff( SyscallInfo.save, HW_EBX ); HW_CTurnOff( SyscallInfo.save, HW_ECX ); HW_CTurnOff( SyscallInfo.save, HW_EDX ); #else HW_CTurnOff( SyscallInfo.save, HW_ABCD ); HW_CTurnOff( SyscallInfo.save, HW_ES ); #endif #if _CPU == 386 /**************************************************** * OS/2 32-bit->16-bit calling convention ( _Far16 ) ****************************************************/ /* these are internal, and will never be pointed to by * an aux_entry, so we don't have to worry about them */ Far16CdeclInfo = CdeclInfo; Far16CdeclInfo.cclass |= FAR16_CALL; Far16CdeclInfo.parms = StackParms; Far16CdeclInfo.objname = AUX_STRALLOC( CdeclInfo.objname ); // __far16 __cdecl depends on EBX being trashed in __cdecl // but NT 386 __cdecl preserves EBX HW_CTurnOff( Far16CdeclInfo.save, HW_EBX ); Far16PascalInfo = PascalInfo; Far16PascalInfo.cclass |= FAR16_CALL; Far16PascalInfo.parms = StackParms; Far16PascalInfo.objname = AUX_STRALLOC( PascalInfo.objname ); #endif }
/* // This section is for // 8086 // 386 // // pass auxiliary information to back end */ CGPOINTER FEAuxInfo( CGPOINTER req_handle, int request ) { aux_info *inf; auto SYM_ENTRY sym; static hw_reg_set save_set; switch( request ) { case SOURCE_LANGUAGE: return( (CGPOINTER)"C" ); case STACK_SIZE_8087: return( (CGPOINTER)(pointer_int)Stack87 ); case CODE_GROUP: return( (CGPOINTER)GenCodeGroup ); case DATA_GROUP: return( (CGPOINTER)DataSegName ); case OBJECT_FILE_NAME: return( (CGPOINTER)ObjFileName() ); case REVISION_NUMBER: return( (CGPOINTER)(pointer_int)II_REVISION ); case AUX_LOOKUP: return( req_handle ); case PROEPI_DATA_SIZE: return( (CGPOINTER)(pointer_int)ProEpiDataSize ); case DBG_PREDEF_SYM: return( (CGPOINTER)SymDFAbbr ); case P5_CHIP_BUG_SYM: return( (CGPOINTER)SymChipBug ); case CODE_LABEL_ALIGNMENT: { static unsigned char Alignment[] = { 2, 1, 1 }; if( OptSize == 0 ) Alignment[1] = TARGET_INT; return( (CGPOINTER)Alignment ); } case CLASS_NAME: return( (CGPOINTER)SegClassName( (segment_id)(pointer_int)req_handle ) ); case USED_8087: CompFlags.pgm_used_8087 = 1; return( NULL ); #if _CPU == 386 case P5_PROF_DATA: return( (CGPOINTER)FunctionProfileBlock ); case P5_PROF_SEG: return( (CGPOINTER)(pointer_int)FunctionProfileSegment ); #endif case SOURCE_NAME: if( SrcFName == ModuleName ) { return( (CGPOINTER)FNameFullPath( FNames ) ); } else { return( (CGPOINTER)ModuleName ); } case CALL_CLASS: { static call_class cclass; cclass = GetCallClass( req_handle ); return( (CGPOINTER)&cclass ); } case FREE_SEGMENT: return( NULL ); case NEXT_LIBRARY: case LIBRARY_NAME: return( NextLibrary( (int)(pointer_int)req_handle, request ) ); case NEXT_IMPORT: case IMPORT_NAME: return( NextImport( (int)(pointer_int)req_handle, request ) ); case NEXT_IMPORT_S: case IMPORT_NAME_S: return( NextImportS( (int)(pointer_int)req_handle, request ) ); case NEXT_ALIAS: case ALIAS_NAME: case ALIAS_SYMBOL: case ALIAS_SUBST_NAME: case ALIAS_SUBST_SYMBOL: return( NextAlias( (int)(pointer_int)req_handle, request ) ); case TEMP_LOC_NAME: return( (CGPOINTER)(pointer_int)TEMP_LOC_QUIT ); case TEMP_LOC_TELL: return( NULL ); case NEXT_DEPENDENCY: if( CompFlags.emit_dependencies ) return( (CGPOINTER)NextDependency( (FNAMEPTR)req_handle ) ); return( NULL ); case DEPENDENCY_TIMESTAMP: return( (CGPOINTER)getFileDepTimeStamp( (FNAMEPTR)req_handle ) ); case DEPENDENCY_NAME: return( (CGPOINTER)FNameFullPath( (FNAMEPTR)req_handle ) ); case PEGGED_REGISTER: return( (CGPOINTER)SegPeggedReg( (segment_id)(pointer_int)req_handle ) ); default: break; } inf = FindInfo( &sym, req_handle ); switch( request ) { case SAVE_REGS: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } else { sym.mods = 0; } save_set = inf->save; if( sym.mods & FLAG_SAVEREGS ) { HW_CTurnOn( save_set, HW_SEGS ); } #ifdef __SEH__ if( (SYM_HANDLE)req_handle == SymTryInit ) { HW_CTurnOff( save_set, HW_SP ); } #endif return( (CGPOINTER)&save_set ); case RETURN_REG: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } return( (CGPOINTER)&inf->returns ); case CALL_BYTES: return( (CGPOINTER)inf->code ); case PARM_REGS: #ifdef __SEH__ if(( (SYM_HANDLE)req_handle == SymTryInit ) || ( (SYM_HANDLE)req_handle == SymTryFini ) || ( (SYM_HANDLE)req_handle == SymTryUnwind ) || ( (SYM_HANDLE)req_handle == SymExcept )) { return( (CGPOINTER)TryParms ); } #endif if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); if( inf->code == NULL && VarFunc( &sym ) ) { return( (CGPOINTER)DefaultVarParms ); } } return( (CGPOINTER)inf->parms ); case STRETURN_REG: if( req_handle != 0 ) { inf = LangInfo( sym.mods, inf ); } return( (CGPOINTER)&inf->streturn ); default: break; } return( NULL ); }