ppcproc.c

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

C
582
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  PowerPC procedure prolog/epilog generation.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "procdef.h"
#include "symdbg.h"
#include "offset.h"
#include "pattern.h"
#include "sysmacro.h"
#include "model.h"
#include "ppcenc.h"
#include "ppcparm.h"
#include "ppcgen.h"

extern  uint_32         CountBits( uint_32 );
extern  seg_id          SetOP( seg_id );
extern  seg_id          AskCodeSeg( void );
extern  unsigned        DepthAlign( unsigned );
extern  void            CodeLabel( label_handle, unsigned );
extern  hw_reg_set      *GPRegs( void );
extern  hw_reg_set      *FPRegs( void );
extern  hw_reg_set      SaveRegs( void );
extern  pointer         CGAlloc( unsigned );
extern  void            CGFree( pointer );
extern  hw_reg_set      FrameBaseReg( void );
extern  sym_handle      AskForLblSym( label_handle );
extern  fe_attr         FEAttr( sym_handle );
extern  void            DbgRtnBeg( dbg_rtn *rtn,  offset lc );
extern  void            DbgProEnd( dbg_rtn *rtn, offset lc );
extern  void            DbgEpiBeg( dbg_rtn *rtn, offset lc );
extern  void            DbgRtnEnd( dbg_rtn *rtn, offset lc );
extern  offset          AskLocation( void );
extern  void            OutFuncStart( label_handle label, offset start, int line );
extern  void            OutFileStart( int line );
extern  void            OutFuncEnd( offset end );
extern void             OutPDataRec( label_handle label, uint_32 pro_size, uint_32 proc_end );
extern  uint_8          RegTrans(hw_reg_set);
extern  void            OutTOCRec( label_handle lbl );
extern  type_length     TempLocation( name * );

extern  proc_def        *CurrProc;
extern  block           *HeadBlock;
extern  type_length     MaxStack;


static  void    CalcUsedRegs( void )
/**********************************/
{
    block       *blk;
    instruction *ins;
    name        *result;
    hw_reg_set  used;

    CurrProc->targ.leaf = TRUE;
    HW_CAsgn( used, HW_EMPTY );
    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            result = ins->result;
            if( result != NULL && result->n.class == N_REGISTER ) {
                HW_TurnOn( used, result->r.reg );
            }
            /* place holder for big label doesn't really zap anything*/
            if( ins->head.opcode != OP_NOP ) {
                HW_TurnOn( used, ins->zap->reg );
            }
            if( ins->head.opcode == OP_CALL ||
                ins->head.opcode == OP_CALL_INDIRECT ) {
                CurrProc->targ.leaf = FALSE;
            }
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
    HW_TurnOn( CurrProc->state.used, used );
}

extern  void    AddCacheRegs( void )
/**********************************/
{
    if( !CurrProc->targ.base_is_fp ) {
        HW_TurnOff( CurrProc->state.unalterable, FrameBaseReg() );
    }
}

#define _unused( x )    ( (x) = (x) )

static  void    initParmCache( stack_record *pc, type_length *offset )
/********************************************************************/
{
    pc->start = *offset;
    pc->size = MaxStack;
    if( !CurrProc->targ.leaf ) {
        if( pc->size < ( 8 * 4 ) ) {
            pc->size = 8 * 4;
        }
    }
    if( pc->size > 0 ) {
        *offset += MaxStack;
    }
}

static  void    emitParmCacheProlog( stack_record *pc )
/*****************************************************/
{
    _unused( pc );
}

static  void    emitParmCacheEpilog( stack_record *pc )
/*****************************************************/
{
    _unused( pc );
}

static  void    initLocals( stack_record *locals, type_length *offset )
/*********************************************************************/
{
    locals->start = *offset;
    locals->size = CurrProc->locals.size;
    *offset += locals->size;
}

static  void    emitLocalProlog( stack_record *locals )
/*****************************************************/
{
    _unused( locals );
}

static  void    emitLocalEpilog( stack_record *locals )
/*****************************************************/
{
    _unused( locals );
}

static  uint_32 registerMask( hw_reg_set rs, hw_reg_set *rl )
/***********************************************************/
{
    hw_reg_set          *curr;
    uint_32             result;

    result = 0;
    for( curr = rl; !HW_CEqual( *curr, HW_EMPTY ); curr++ ) {
        if( HW_Ovlap( rs, *curr ) ) {
            result |= 1 << RegTrans( *curr );
        }
    }
    return( result );
}

static  void    initSavedRegs( stack_record *saved_regs, type_length *offset )
/****************************************************************************/
{
    unsigned            num_regs;
    hw_reg_set          saved;

    saved = SaveRegs();
    if( CurrProc->targ.base_is_fp ) {
        HW_TurnOn( saved, FrameBaseReg() );
    }
#if 1
    // saved in previous frame's LR-save location below
    if( !CurrProc->targ.leaf ) {
        // this is really the value of LR (set up by first ins)
        HW_CTurnOn( saved, HW_D0 );
    }
#endif
    CurrProc->targ.gpr_mask = registerMask( saved, GPRegs() );
    CurrProc->targ.fpr_mask = registerMask( saved, FPRegs() );
    num_regs  = CountBits( CurrProc->targ.gpr_mask );
    num_regs += CountBits( CurrProc->targ.fpr_mask );
    saved_regs->size = num_regs * REG_SIZE;
    saved_regs->start = *offset;
    *offset += saved_regs->size;
}

#define STORE_DWORD     36
#define STORE_DOUBLE    54
#define LOAD_DWORD      32
#define LOAD_DOUBLE     50
#define ADDI_OPCODE     14

#define STACK_REG       1
#define FRAME_REG       31
#define VARARGS_PTR     14

static  void    genMove( uint_32 src, uint_32 dst )
/*************************************************/
{
    GenOPINS( 31, 444, dst, src, src );
}

static  void    genAdd( uint_32 src, signed_16 disp, uint_32 dst )
/****************************************************************/
{
    GenOPIMM( ADDI_OPCODE, dst, src, disp );
}

static  void    saveReg( uint_32 index, type_length offset, bool fp )
/*******************************************************************/
{
    uint_8              opcode;

    opcode = STORE_DWORD;
    if( fp ) {
        opcode = STORE_DOUBLE;
    }
    GenMEMINS( opcode, index, STACK_REG, offset );
}

static  void    loadReg( uint_32 index, type_length offset, bool fp )
/*******************************************************************/
{
    uint_8              opcode;
    uint_8              frame_reg;

    opcode = LOAD_DWORD;
    if( fp ) {
        opcode = LOAD_DOUBLE;
    }
    frame_reg = STACK_REG;
    if( CurrProc->targ.base_is_fp ) {
        frame_reg = FRAME_REG;
    }
    GenMEMINS( opcode, index, frame_reg, offset + CurrProc->locals.size );
}

static  int     regSize( bool fp )
/********************************/
{
    return( fp ? 8 : 4 );
}

static  void    saveRegSet( uint_32 reg_set, type_length offset, bool fp )
/************************************************************************/
{
    uint_32     index;
    uint_32     high_bit;

    index = sizeof( reg_set ) * 8 - 1;
    high_bit = 1 << index;
    while( reg_set != 0 ) {
        if( reg_set & high_bit ) {
            offset -= regSize( fp );
            saveReg( index, offset, fp );
        }
        reg_set <<= 1;
        index -= 1;
    }
}

static  void    loadRegSet( uint_32 reg_set, type_length offset, bool fp )
/************************************************************************/
{
    uint_32     index;

    index = 0;
    while( reg_set != 0 ) {
        if( reg_set & 1 ) {
            loadReg( index, offset, fp );
            offset += regSize( fp );

⌨️ 快捷键说明

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