axpproc.c

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

C
668
字号
/****************************************************************************
*
*                            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:  Alpha AXP 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 "regset.h"
#include "rttable.h"
#include "rtclass.h"
#include "zoiks.h"
#include "axpencod.h"
#include "feprotos.h"

extern  uint_32         CountBits( uint_32 );
extern  seg_id          SetOP( seg_id );
extern  seg_id          AskCodeSeg( void );
extern  unsigned        DepthAlign( unsigned );
extern  void            CodeLabelLinenum( label_handle, unsigned, cg_linenum );
extern  void            CodeLabel( label_handle, unsigned );
extern  hw_reg_set      *GPRegs( void );
extern  hw_reg_set      *FPRegs( void );
extern  hw_reg_set      *ParmRegs( void );
extern  hw_reg_set      SaveRegs( void );
extern  void            GenMEMINS( uint_8, uint_8, uint_8, signed_16 );
extern  void            GenOPINS( uint_8, uint_8, uint_8, uint_8, uint_8 );
extern  pointer         CGAlloc( unsigned );
extern  void            CGFree( pointer );
extern  hw_reg_set      StackReg( void );
extern  hw_reg_set      ScratchReg( void );
extern  hw_reg_set      VarargsHomePtr( void );
extern  void            GenRET( void );
extern  sym_handle      AskForLblSym( label_handle );
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  hw_reg_set      FrameBaseReg(void);
extern  uint_8          RegTrans(hw_reg_set);
extern  void            GenCallLabelReg( label_handle lbl, uint reg );
extern  label_handle    RTLabel( int );
extern  type_length     TempLocation( name * );
extern  hw_reg_set      ReturnAddrReg( void );
extern  void            FactorInt32( signed_32, signed_16 *, signed_16 *, signed_16 * );
extern  void            EmitRtnBeg( void );
extern  void            EmitProEnd( void );
extern  void            EmitEpiBeg( void );
extern  void            EmitRtnEnd( void );
extern  void            EmitFuncStart( label_handle, cg_linenum );
extern  void            TellKeepLabel( label_handle );
extern  void            TellProcLabel( label_handle );
extern  void            GenLOADS32( signed_32, uint_8 );

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;

    HW_CAsgn( used, HW_EMPTY );
    blk = HeadBlock;
    while( blk != NULL ) {
        if( ( blk->class & CALL_LABEL ) != EMPTY ) {
            HW_TurnOn( used, ReturnAddrReg() );
        }
        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 );
            }
            /* placeholder for big label doesn't really zap anything */
            if( ins->head.opcode != OP_NOP ) {
                HW_TurnOn( used, ins->zap->reg );
            }
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
    if( FEAttr( AskForLblSym( CurrProc->label ) ) & FE_VARARGS ) {
        HW_TurnOn( used, VarargsHomePtr() );
    }
    HW_TurnOn( CurrProc->state.used, used );
}


extern  void    AddCacheRegs( void )
/**********************************/
{
}

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

static  void    initParmCache( stack_record *pc, type_length *offset )
/********************************************************************/
{
    pc->start = *offset;
    pc->size = MaxStack;
    if( MaxStack > 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;

    calcUsedRegs();
    saved = SaveRegs();
    if( FEAttr( AskForLblSym( CurrProc->label ) ) & FE_VARARGS ) {
        HW_TurnOn( saved, VarargsHomePtr() );
    }
    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_QUADWORD  0x2d
#define STORE_DOUBLE    0x27
#define LOAD_QUADWORD   0x29
#define LOAD_DOUBLE     0x23
#define LEA_OPCODE      0x08
#define LEAH_OPCODE     0x09

#define VARARGS_PTR     14
#define RT_PARM2        2
#define RT_PARM1        1
#define RT_RET_REG      0


static  void    genMove( uint_32 src, uint_32 dst )
/*************************************************/
{
    GenOPINS( 0x11, 0x20, AXP_ZERO_SINK, src, dst );
}


static  void    genLea( uint_32 src, signed_16 disp, uint_32 dst )
/****************************************************************/
{
    GenMEMINS( LEA_OPCODE, dst, src, disp );
}


static  uint_32 addressableRegion( stack_record *region, type_length *offset )
/****************************************************************************/
{
    if( region->start > AXP_MAX_OFFSET ) {
        *offset = 0;
        GenLOADS32( region->start, AXP_GPR_SCRATCH );
        // add sp, r28 -> r28
        GenOPINS( 0x10, 0x00, AXP_STACK_REG, AXP_GPR_SCRATCH, AXP_GPR_SCRATCH );
        return( AXP_GPR_SCRATCH );
    } else {
        *offset = region->start;
        return( AXP_STACK_REG );
    }
}


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

    opcode = STORE_QUADWORD;
    if( fp ) {
        opcode = STORE_DOUBLE;
    }
    GenMEMINS( opcode, index, reg, offset );
}


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

    opcode = LOAD_QUADWORD;
    if( fp ) {
        opcode = LOAD_DOUBLE;
    }
    GenMEMINS( opcode, index, reg, offset );
}


static  void    saveRegSet( uint_32 index_reg,
                        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 -= 8;
            saveReg( index_reg, index, offset, fp );
        }
        reg_set <<= 1;
        index -= 1;
    }
}


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

    index = 0;
    while( reg_set != 0 ) {
        if( reg_set & 1 ) {
            loadReg( index_reg, index, offset, fp );
            offset += 8;
        }
        index++;
        reg_set >>= 1;
    }
}


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

    index_reg = addressableRegion( saved_regs, &offset );
    offset += saved_regs->size;
    saveRegSet( index_reg, CurrProc->targ.gpr_mask, offset, FALSE );

⌨️ 快捷键说明

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