i87sched.c

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

C
1,092
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "vergen.h"
#include "pattern.h"
#include "zoiks.h"
#include "sysmacro.h"
#include "gen8087.h"
#include "model.h"
#include "i87sched.h"

extern  block   *HeadBlock;
extern  int     Max87Stk;

extern  instruction     *PrefFXCH( instruction *ins, int i );
extern  instruction     *SuffFXCH( instruction *ins, int i );
extern  instruction     *PrefFLDOp(instruction *,operand_types ,name *);
extern  instruction     *SuffFSTPRes(instruction *,name *,result_type );
extern  name            *ST(int);
extern  int             NumOperands(instruction*);
extern  int             FPRegNum(name*);
extern  void            *SortList(void *,unsigned,bool (*)(void*,void*) );
extern  void            DoNothing(instruction*);
extern  int             Count87Regs(hw_reg_set);
extern  bool            ReDefinedBy(instruction*,name*);
extern  name            *DeAlias(name*);
extern  void            MoveEdge( block_edge *edge, block *new_dest );
extern  block           *AddPreBlock( block *postblk );
extern  bool            FPStackIns( instruction *ins );
extern  void            RevCond( instruction * );
extern  int             FPStkReq( instruction * );
extern  bool            InsOrderDependant( instruction *, instruction * );

/* forward declarations */
static  void            PushStack( instruction *ins );
static  void            IncrementAll( void );
static  void            DecrementAll( void );
static  void            PopStack( instruction *ins );
static  void            PushVirtualStack( instruction *ins );
static  void            GetToTopOfStack( instruction *ins, int virtual_reg );
static  void            PopVirtualStack( instruction *ins );


static  opcode_entry    RFST    = { PRESERVE, 0, G_RFST,   0, 0 };
static  opcode_entry    RFSTNP  = { PRESERVE, 0, G_RFSTNP, 0, 0 };
static  opcode_entry    RFLD    = { PRESERVE, 0, G_RFLD,   0, 0 };
static  opcode_entry    RCOMP   = { PRESERVE, 0, G_RCOMP,  0, 0 };
static  opcode_entry    FCOMPP  = { PRESERVE, 0, G_FCOMPP, 0, 0 };
static  opcode_entry    RRFBIN  = { PRESERVE, 0, G_RRFBIN, 0, 0 };
static  opcode_entry    RNFBIN  = { PRESERVE, 0, G_RNFBIN, 0, 0 };
static  opcode_entry    RRFBINP = { PRESERVE, 0, G_RRFBINP,0, 0 };
static  opcode_entry    RNFBINP = { PRESERVE, 0, G_RNFBINP,0, 0 };

static  block   *Entry;
static  block   *Exit;

// global variables
st_seq          *STLocations;
int             MaxSeq;
byte            *SeqMaxDepth;
byte            *SeqCurDepth;
temp_entry      *TempList;

#define FP_INS_INTRODUCED       INS_VISITED // this must stick!

extern  bool    FPInsIntroduced( instruction *ins ) {
/****************************************************

    Used by the scheduler. We want to make sure that introduced instructions
    stay put.
*/

    return( ( ins->ins_flags & FP_INS_INTRODUCED ) != 0 );
}


extern  bool    FPFreeIns( instruction *ins ) {
/**********************************************

    Return true if "ins" is going to be vaporized by the cacheing
    algorithm in FPPostSched.
*/
    temp_entry  *temp;

    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->whole_block ) {
            if( ins->u.gen_table->generate == G_MFST &&
                temp->actual_op == ins->result ) {
                return( TRUE ); // will likely merge into the previous op
            }
        } else if( ins == temp->first && temp->defined ) {
            return( TRUE );
        } else if( ins == temp->last && ins->u.gen_table->generate == G_MFLD ) {
            return( TRUE );
        }
    }
    return( FALSE );
}

extern  int     FPStkOver( instruction *ins, int stk_depth )
/***********************************************************

    Return >= 0 if scheduling "ins" could get us into a spot that
    we cannot get out of with the amount of stack left. What this
    says is that we can only schedule an instruction in sequence i
    if there's enough stack left to complete sequence i, plus
    the maximum stack requirement of all sequences that might
    need to be scheduled before sequence i can complete. i+1..MaxSeq
    is a conservative (and cheaply calculated) estimate of the
    those dependencies. We know that sequences 0..i-1 are ok since they
    were in front of i in the original ordering.
*/
{
    int         i;
    int         depth;
    int         max_depth;

    max_depth = 0;
    for( i = ins->sequence + 1; i < MaxSeq; ++i ) {
        depth = SeqMaxDepth[ i ] - SeqCurDepth[ i ];
        if( depth > max_depth ) max_depth = depth;
    }
    return( SeqMaxDepth[ins->sequence] - SeqCurDepth[ins->sequence] +
            max_depth + stk_depth - Max87Stk );
}


static  int     InsMaxDepth( instruction *ins )
/********************************************/
{
    if( ins->stk_entry > ins->stk_exit ) return( ins->stk_entry );
    return( ins->stk_exit );
}


extern  void    FPCalcStk( instruction *ins, int *pdepth )
/*********************************************************

    Set pdepth to the stack level before "ins" executes.  Also,
    recalcualte the stk_entry, stk_exit. s.stk_depth
    now means the maximum depth the stack attains during this
    instruction.
*/
{
    int         affect;

    if( FPStackIns( ins ) ) SeqMaxDepth[ ins->sequence ] = ins->t.stk_max;
    affect = ins->stk_entry - ins->stk_exit;
    SeqCurDepth[ ins->sequence ] += affect;
    ins->stk_exit = *pdepth;
    ins->stk_entry = *pdepth + affect;
    ins->s.stk_depth = *pdepth + ins->s.stk_extra;
    if( affect > 0 ) ins->s.stk_depth += affect;
    *pdepth += affect;
}

extern  int     FPStackExit( block *blk ) {
/******************************************
    Return the depth of the FPU stack upon exit from this
    block. This is the stk_exit from the last FPU
    instruction in the block.
*/
    instruction *curr;

    curr = blk->ins.hd.prev;
    while( curr->head.opcode != OP_BLOCK ) {
        if( FPStackIns( curr ) ) return( curr->stk_exit );
        curr = curr->head.prev;
    }
    return( 0 );
}

static  fp_attr FPAttr( instruction *ins ) {
/*******************************************/

    if( _OpIsCall( ins->head.opcode ) && ins->result != NULL ) {
        if( ins->result->n.class != N_REGISTER ) return( POPS_ALL );
        if( !HW_COvlap( ins->result->r.reg, HW_FLTS ) ) return( POPS_ALL );
        return( PUSHES+POPS_ALL );
    }
    if( ins->u.gen_table->generate == G_FCHOP ) return( NEEDS_ST0 );
    if( !_GenIs8087( ins->u.gen_table->generate ) ) {
        return( NEEDS_NOTHING );
    }
    switch( ins->u.gen_table->generate ) {
    case G_RRFBINP:
    case G_RNFBINP:
        return( NEEDS_ST0+POPS+SETS_ST1 );
    case G_MFLD:
    case G_FLDZ:
    case G_FLD1:
    case G_RFLD:
        return( PUSHES );
    case G_FRNDINT:
    case G_FCHS:
    case G_MFSTNP:
    case G_RFSTNP:
    case G_FTST:
    case G_FMATH:
    case G_RRFBIN:
    case G_RNFBIN:
    case G_MRFBIN:
    case G_MNFBIN:
        return( NEEDS_ST0 );
    case G_FCOMPP:
        return( NEEDS_ST0_ST1+POPS2 );
    case G_MFST:
    case G_MFSTRND:
    case G_RFST:
    case G_MCOMP:
    case G_RCOMP:
        return( NEEDS_ST0+POPS );
    case G_IFUNC:
        if( NumOperands( ins ) == 2 ) {
            return( NEEDS_ST0_ST1+POPS );
        } else {
            return( NEEDS_ST0 );
        }
    case G_FXCH:
        return( NEEDS_ST0+EXCHANGES );
    case G_FSINCOS:
    default:
        Zoiks( ZOIKS_075 );
        return( NEEDS_NOTHING );
    }
}


static  opcode_entry    *RegAction( instruction *ins ) {
/*****************************************************/

    switch( ins->u.gen_table->generate ) {
    case G_MFLD:
        return( &RFLD );
    case G_MCOMP:
        return( &RCOMP );
    case G_MRFBIN:
        return( &RRFBIN );
    case G_MNFBIN:
        return( &RNFBIN );
    default:
        return( NULL );
    }
}


static  fp_attr ResultToReg( instruction *ins, temp_entry *temp, fp_attr attr ){
/******************************************************************************/

    if( ins == temp->first && !temp->whole_block ) {
        DoNothing( ins );
        temp->actual_locn = InsLoc( ins, VIRTUAL_0 );
        PopVirtualStack( ins );
        attr &= ~POPS;
    } else {
        GetToTopOfStack( ins, VIRTUAL_0 );
        if( ins->u.gen_table->generate == G_MFST ) {
            ins->u.gen_table = &RFST;
        } else {
            ins->u.gen_table = &RFSTNP;
        }
        ins->result = ST( temp->actual_locn );
    }
    return( attr );
}


static  byte    *ActualStackOwner( int actual ) {
/***********************************************/

    int         i,j;
    temp_entry  *temp;

    for( i = 0; i < MaxSeq; ++i ) {
        for( j = VIRTUAL_0; j < VIRTUAL_NONE; ++j ) {
            if( RegLoc( i, j ) == actual ) {
                return( &RegLoc( i, j ) );
            }
        }
    }
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->actual_locn == actual ) {
            return( &temp->actual_locn );
        }
    }
    return( NULL );
}


static  void    PrefixExchange( instruction *ins, int actual ) {
/************************************************************/

    if( actual != ACTUAL_0 ) {
        PrefFXCH( ins, actual );
    }
}


static instruction *OpToReg( instruction *ins, temp_entry *temp, fp_attr attr ) {
/*****************************************************************************/

    if( ins == temp->last && !temp->whole_block ) {
        switch( ins->u.gen_table->generate ) {
        case G_MFLD:
            PushVirtualStack( ins );
            InsLoc( ins, VIRTUAL_0 ) = temp->actual_locn;
            DoNothing( ins );
            break;
        case G_MCOMP:
            // if( temp->actual_locn != ACTUAL_1 ) _Zoiks( ZOIKS_076 );
            ins->operands[ 0 ] = ST( ACTUAL_1 );
            ins->operands[ 1 ] = ST( 0 );
            if( temp->actual_locn != ACTUAL_1 ) {
                byte    *actual_owner;

                actual_owner = ActualStackOwner( ACTUAL_1 );
                *actual_owner = temp->actual_locn;
                PrefFXCH( ins, ACTUAL_1 );
                PrefFXCH( ins, temp->actual_locn );
                RevCond( ins );
            }
            ins->u.gen_table = &FCOMPP;
            PopStack( ins );
            PopStack( ins );
            break;
        case G_MNFBIN:
        case G_MRFBIN:
            if( ins->u.gen_table->generate == G_MRFBIN ) {
                ins->u.gen_table = &RNFBINP;
            } else {
                ins->u.gen_table = &RRFBINP;
            }

⌨️ 快捷键说明

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