mipsproc.c

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

C
691
字号
    index_reg = addressableRegion( saved_regs, &offset );
    offset += saved_regs->size;
    saveRegSet( index_reg, CurrProc->targ.gpr_mask, offset, FALSE );
    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 = 4 * 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;
        // four registers starting at $4 (ie. $a0-$a3)
        saveRegSet( index_reg, 0x0f << 4, 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, MIPS_FRAME_REG, offset, FALSE );
    }
}


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

    // NB This instruction must immediately preceed 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, MIPS_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;
        // Skip hidden parameter in first register
        if( CurrProc->targ.return_points != NULL ) {
            offset += REG_SIZE;
        }
        if( offset > MIPS_MAX_OFFSET ) {
            GenLOADS32( offset, VARARGS_PTR );
            // 'add va_home,va_home,sp'
            GenRType( 0x00, 0x21, MIPS_STACK_REG, VARARGS_PTR, VARARGS_PTR );
        } else {
            genLoadImm( MIPS_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 <= MIPS_MAX_OFFSET ) {
            genLoadImm( MIPS_STACK_REG, -frame_size, MIPS_STACK_REG );
        } else {
            GenLOADS32( frame_size, MIPS_GPR_SCRATCH );
            // 'subu sp,sp,at'
            GenRType( 0x00, 0x23, MIPS_STACK_REG, MIPS_STACK_REG, MIPS_GPR_SCRATCH );
        }
        if( frame_size >= PAGE_SIZE ) {
            GenCallLabelReg( RTLabel( RT_STK_CRAWL_SIZE ), RT_RET_REG );
            // Next instruction will be in delay slot!
            if( frame_size <= MIPS_MAX_OFFSET ) {
                genLoadImm( MIPS_ZERO_SINK, frame_size, RT_PARM1 );
            } else {
                genMove( MIPS_GPR_SCRATCH, RT_PARM1 );
            }
        }
    }
    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 > MIPS_MAX_OFFSET ) {
                GenLOADS32( size, RT_PARM1 );
                GenCallLabelReg( RTLabel( RT_STK_STOMP ), RT_RET_REG );
                genNOP();   // could split LOADS32 call to fill in delay slot...
            } else {
                GenCallLabelReg( RTLabel( RT_STK_STOMP ), RT_RET_REG );
                // Next instruction will be in delay slot!
                genLoadImm( MIPS_ZERO_SINK, map->locals.size + map->parm_cache.size, RT_PARM1 );
            }
        }
    }
    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( MIPS_STACK_REG, MIPS_FRAME_REG );
    }
}

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

    if( map->frame_save.size != 0 ) {
        // NB should just use MIPS_FRAME_REG instead of MIPS_STACK_REG in restore
        // code and not bother emitting this instruction
        genMove( MIPS_FRAME_REG, MIPS_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 <= MIPS_MAX_OFFSET ) {
            genLoadImm( MIPS_STACK_REG, frame_size, MIPS_STACK_REG );
        } else {
            GenLOADS32( frame_size, MIPS_GPR_SCRATCH );
            // 'addu sp,sp,at'
            GenRType( 0x00, 0x21, MIPS_STACK_REG, MIPS_STACK_REG, MIPS_GPR_SCRATCH );
        }
    }
}


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;
    calcUsedRegs();
    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 + -
显示快捷键?