Exemple #1
0
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
}
Exemple #2
0
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( "*" );
}
Exemple #3
0
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;
        }
    }
}
Exemple #4
0
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;
        }
    }
}
Exemple #5
0
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;
        }
    }
}
Exemple #6
0
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 );
}
Exemple #7
0
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 );
}
Exemple #8
0
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();
}
Exemple #9
0
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 );
    }
}
Exemple #10
0
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();
}
Exemple #11
0
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 );
    }
}
Exemple #12
0
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;
    }
}
Exemple #13
0
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 );
    }
}
Exemple #14
0
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 );
}
Exemple #15
0
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 );
}
Exemple #16
0
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( '}' );
            }
        }
Exemple #17
0
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 );
}
Exemple #18
0
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
}
Exemple #19
0
/*
//    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 );
}