axpproc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 668 行 · 第 1/2 页

C
668
字号
    offset -= CountBits( CurrProc->targ.gpr_mask ) * REG_SIZE;
    saveRegSet( index_reg, CurrProc->targ.fpr_mask, offset, TRUE );
}


static  void    emitSavedRegsEpilog( stack_record *saved_regs )
/*************************************************************/
{
    type_length         offset;
    uint_32             index_reg;

    index_reg = addressableRegion( saved_regs, &offset );
    loadRegSet( index_reg, CurrProc->targ.fpr_mask, offset, TRUE );
    offset += CountBits( CurrProc->targ.fpr_mask ) * REG_SIZE;
    loadRegSet( index_reg, CurrProc->targ.gpr_mask, offset, FALSE );
}


static  void    initVarargs( stack_record *varargs, type_length *offset )
/***********************************************************************/
{
    sym_handle          sym;
    fe_attr             attr;

    varargs->start = *offset;
    varargs->size = 0;
    sym = AskForLblSym( CurrProc->label );
    attr = FEAttr( sym );
    if( attr & FE_VARARGS ) {
        varargs->size = 12 * REG_SIZE;
        *offset += varargs->size;
    }
}


static  void    emitVarargsProlog( stack_record *varargs )
/********************************************************/
{
    type_length         offset;
    uint_32             index_reg;

    if( varargs->size != 0 ) {
        index_reg = addressableRegion( varargs, &offset );
        offset += varargs->size;
        saveRegSet( index_reg, 0x3f << 16, offset, FALSE );
        offset -= 6 * REG_SIZE;
        saveRegSet( index_reg, 0x3f << 16, offset, TRUE );
    }
}


static  void    emitVarargsEpilog( stack_record *varargs )
/********************************************************/
{
    // NB see FrameSaveEpilog below
    _unused( varargs );
}


static  void    initFrameSave( stack_record *fs, type_length *offset )
/********************************************************************/
{
    fs->start = *offset;
    fs->size = 0;
    if( CurrProc->targ.base_is_fp ) {
        fs->size = REG_SIZE;
        *offset += fs->size;
    }
}


static  void    emitFrameSaveProlog( stack_record *fs )
/*****************************************************/
{
    uint_32     index_reg;
    type_length offset;

    if( fs->size != 0 ) {
        index_reg = addressableRegion( fs, &offset );
        saveReg( index_reg, AXP_FRAME_REG, offset, FALSE );
    }
}


static  void    emitFrameSaveEpilog( stack_record *fs )
/*****************************************************/
{
    uint_32     index_reg;
    type_length offset;

    // NB This instruction must immediately precede the
    // stack restoration instruction - which means that the
    // varargs epilog above must be empty
    if( fs->size != 0 ) {
        index_reg = addressableRegion( fs, &offset );
        loadReg( index_reg, AXP_FRAME_REG, offset, FALSE );
    }
}


static  void    initSlop( stack_record *slop, type_length *offset )
/*****************************************************************/
{
    type_length         off;

    off = *offset;
    slop->start = off;
    slop->size = 0;
    if( off & (STACK_ALIGNMENT - 1) ) {
        slop->size = STACK_ALIGNMENT - (off & (STACK_ALIGNMENT - 1));
        *offset += slop->size;
    }
}


static  void    emitSlopProlog( stack_record *fs )
/************************************************/
{
    _unused( fs );
}


static  void    emitSlopEpilog( stack_record *fs )
/************************************************/
{
    _unused( fs );
}


static  signed_32 frameSize( stack_map *map )
/*******************************************/
{
    signed_32           size;

    size = map->slop.size + map->varargs.size + map->frame_save.size + map->saved_regs.size +
                map->locals.size + map->parm_cache.size;
    assert( (size & (STACK_ALIGNMENT - 1)) == 0 );
    return( size );
}


static  void    initStackLayout( stack_map *map )
/***********************************************/
{
    type_length         offset;

    offset = 0;
    initParmCache( &map->parm_cache, &offset );
    initLocals( &map->locals, &offset );
    initSavedRegs( &map->saved_regs, &offset );
    initFrameSave( &map->frame_save, &offset );
    initSlop( &map->slop, &offset );
    initVarargs( &map->varargs, &offset );
}


static  void    SetupVarargsReg( stack_map *map )
/***********************************************/
{
    if( map->varargs.size != 0 ) {
        type_length     offset;

        offset = map->varargs.start + 6 * REG_SIZE;
        // Skip hidden parameter in first register
        if( CurrProc->targ.return_points != NULL ) {
            offset += REG_SIZE;
        }
        if( offset > AXP_MAX_OFFSET ) {
            GenLOADS32( offset, VARARGS_PTR );
            GenOPINS( 0x10, 0x00, AXP_STACK_REG, VARARGS_PTR, VARARGS_PTR );
        } else {
            genLea( AXP_STACK_REG, offset, VARARGS_PTR );
        }
    }
}


static  void    emitProlog( stack_map *map )
/******************************************/
{
    type_length         frame_size;

    frame_size = frameSize( map );
    if( frame_size != 0 ) {
        if( frame_size <= AXP_MAX_OFFSET ) {
            genLea( AXP_STACK_REG, -frame_size, AXP_STACK_REG );
        } else {
            GenLOADS32( frame_size, AXP_GPR_SCRATCH );
            // sub sp,r28 -> sp
            GenOPINS( 0x10, 0x09, AXP_STACK_REG, AXP_GPR_SCRATCH, AXP_STACK_REG );
        }
        if( frame_size >= PAGE_SIZE ) {
            if( frame_size <= AXP_MAX_OFFSET ) {
                genLea( AXP_ZERO_SINK, frame_size, RT_PARM1 );
            } else {
                genMove( AXP_GPR_SCRATCH, RT_PARM1 );
            }
            GenCallLabelReg( RTLabel( RT_STK_CRAWL_SIZE ), RT_RET_REG );
        }
    }
    if( map->locals.size != 0 || map->parm_cache.size != 0 ) {
        if( _IsTargetModel( STACK_INIT ) ) {
            type_length         size;
            size = map->locals.size + map->parm_cache.size;
            if( size > AXP_MAX_OFFSET ) {
                GenLOADS32( size, RT_PARM1 );
            } else {
                genLea( AXP_ZERO_SINK, map->locals.size + map->parm_cache.size, RT_PARM1 );
            }
            GenCallLabelReg( RTLabel( RT_STK_STOMP ), RT_RET_REG );
        }
    }
    emitVarargsProlog( &map->varargs );
    emitSlopProlog( &map->slop );
    emitFrameSaveProlog( &map->frame_save );
    emitSavedRegsProlog( &map->saved_regs );
    emitLocalProlog( &map->locals );
    emitParmCacheProlog( &map->parm_cache );
    if( map->frame_save.size != 0 ) {
        genMove( AXP_STACK_REG, AXP_FRAME_REG );
    }
}


static  void    emitEpilog( stack_map *map )
/******************************************/
{
    type_length         frame_size;

    if( map->frame_save.size != 0 ) {
        // NB should just use AXP_FRAME_REG instead of AXP_STACK_REG in restore
        // code and not bother emitting this instruction
        genMove( AXP_FRAME_REG, AXP_STACK_REG );
    }
    emitParmCacheEpilog( &map->parm_cache );
    emitLocalEpilog( &map->locals );
    emitSavedRegsEpilog( &map->saved_regs );
    emitFrameSaveEpilog( &map->frame_save );
    emitSlopEpilog( &map->slop );
    emitVarargsEpilog( &map->varargs );
    frame_size = frameSize( map );
    if( frame_size != 0 ) {
        if( frame_size <= AXP_MAX_OFFSET ) {
            genLea( AXP_STACK_REG, frame_size, AXP_STACK_REG );
        } else {
            GenLOADS32( frame_size, AXP_GPR_SCRATCH );
            GenOPINS( 0x10, 0x00, AXP_STACK_REG, AXP_GPR_SCRATCH, AXP_STACK_REG );
        }
    }
}


extern  void    GenProlog( void )
/*******************************/
{
    seg_id              old;
    label_handle        label;

    old = SetOP( AskCodeSeg() );
    label = CurrProc->label;
    if( _IsModel( NUMBERS ) ) {
        OutFileStart( HeadBlock->ins.hd.line_num );
    }
    TellKeepLabel( label );
    TellProcLabel( label );
    CodeLabelLinenum( label, DepthAlign( PROC_ALIGN ), HeadBlock->ins.hd.line_num );
    if( _IsModel( DBG_LOCALS ) ) {  // d1+ or d2
        // DbgRtnBeg( CurrProc->targ.debug, lc );
        EmitRtnBeg( /*label, HeadBlock->ins.hd.line_num*/ );
    }
    // keep stack aligned
    CurrProc->locals.size = _RoundUp( CurrProc->locals.size, REG_SIZE );
    CurrProc->parms.base = 0;
    CurrProc->parms.size = CurrProc->state.parm.offset;
    initStackLayout( &CurrProc->targ.stack_map );
    emitProlog( &CurrProc->targ.stack_map );
    EmitProEnd();
    SetupVarargsReg( &CurrProc->targ.stack_map );
    CurrProc->targ.frame_size = frameSize( &CurrProc->targ.stack_map );
    SetOP( old );
}


extern  void    GenEpilog( void )
/*******************************/
{
    seg_id              old;

    old = SetOP( AskCodeSeg() );
    EmitEpiBeg();
    emitEpilog( &CurrProc->targ.stack_map );
    GenRET();
    CurrProc->prolog_state |= GENERATED_EPILOG;
    EmitRtnEnd();
    SetOP( old );
}


extern  int     AskDisplaySize( int level )
/*****************************************/
{
    level = level;
    return( 0 );
}


extern  void    InitStackDepth( block *blk )
/******************************************/
{
    blk = blk;
}


extern  type_length     PushSize( type_length len )
/*************************************************/
{
    if( len < REG_SIZE ) return( REG_SIZE );
    return( len );
}


extern  type_length     NewBase( name *op )
/*****************************************/
{
    return( TempLocation( op ) );
}


extern  int     ParmsAtPrologue( void )
/*************************************/
{
    return( 0 );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?