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 + -
显示快捷键?