i87opt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 906 行 · 第 1/3 页
C
906 行
/****************************************************************************
*
* 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 "opcodes.h"
#include "coderep.h"
#include "pattern.h"
#include "vergen.h"
#include "gen8087.h"
#include "procdef.h"
#include "addrname.h"
#include "model.h"
#include "sysmacro.h"
#include "regset.h"
#include "zoiks.h"
#include "funits.h"
extern block *HeadBlock;
extern block *CurrBlock;
extern name *Parm8087[];
extern hw_reg_set *RegSets[];
extern hw_reg_set FPRegs[];
extern proc_def *CurrProc;
extern bool BlockByBlock;
extern byte OptForSize;
extern int Max87Stk;
extern int FPRegNum(name*);
extern void DoNothing(instruction*);
extern name *AllocRegName(hw_reg_set);
extern void BGDone(an);
extern bool FPIsStack(name*);
extern bool ReDefinedBy(instruction*,name*);
extern instruction *MakeNary(opcode_defs,name*,name*,name*,type_class_def,type_class_def,int);
extern void AddIns(instruction*);
extern name *BGNewTemp(type_def*);
extern instruction *MakeMove(name*,name*,type_class_def);
extern type_class_def TypeClass(type_def*);
extern bool DoesSomething(instruction*);
extern void ToRFld(instruction*);
extern void ToRFstp(instruction*);
extern void NoPop(instruction*);
extern void NoPopBin(instruction*);
extern void NoPopRBin(instruction*);
extern void ToPopBin(instruction*);
extern void NoMemBin(instruction*);
extern name* ST(int);
extern int NumOperands(instruction*);
extern bool IsVolatile(name*);
extern opcode_entry *FindGenEntry(instruction*,bool*);
extern void DupSeg(instruction*,instruction*);
extern void DelSeg(instruction*);
extern name *LowPart(name*,type_class_def);
extern name *HighPart(name*,type_class_def);
extern void PrefixIns(instruction*,instruction*);
extern void SuffixIns(instruction*,instruction*);
extern void UpdateLive(instruction*,instruction*);
extern void PrefFXCH(instruction*,int);
extern void Wait8087( void );
extern void FreeIns(instruction*);
extern void ReverseFPGen(instruction*);
extern bool InsOrderDependant(instruction*,instruction*);
extern int FPStkReq(instruction*);
extern bool FPResultNotNeeded(instruction*);
extern void ReserveStack( call_state *, instruction *, type_length );
/* forward declarations */
static void MoveThrough( name *from, name *to, instruction *from_ins,
instruction *to_ins, name *reg,
type_class_def class );
extern void Opt8087( void );
extern void FPParms( void ) {
/**************************
Find sequences like
PARM_DEF => ST(0),
MOV ST(0) => foobar
in HeadBlock and record where the parameters in the 8087 are going
to end up in Parm8087, so that the code to deal with the parameters
can be folded into the prolog sequence.
*/
instruction *ins;
instruction *next;
int i;
if( CurrProc->label == HeadBlock->label ) {
i = MAX_8087_REG + 1;
while( --i >= 0 ) {
Parm8087[ i ] = NULL;
}
ins = HeadBlock->ins.hd.next;
i = 0;
while( ins->head.opcode != OP_BLOCK ) {
if( ins->head.opcode == OP_PARM_DEF ) {
if( FPRegNum( ins->result ) == 0 ) {
next = ins->head.next;
if( next->head.opcode == OP_BLOCK
|| (instruction *)ins->operands[ 2 ] != next /* not associated*/
|| (instruction *)next->operands[ 2 ] != ins ) {
Parm8087[ i ] = (name *)CurrProc; /* klude - means parm ignored*/
} else {
Parm8087[ i ] = next->result;
DoNothing( next );
ins = next;
}
++i;
}
}
ins = ins->head.next;
}
}
}
static bool CanPushImmed( pn parm, int *num_parms ) {
/********************************************************
find out if we can "push" floating point parameters onto the 8087
stack immediately as they are calculated, or if we must delay
pushing until just before the call instruction.
*/
instruction *next;
instruction *ins;
an addr;
while( parm != NULL ) {
if( parm->ins != NULL ) {
parm = parm->next;
continue;
}
addr = parm->name;
if( addr->tipe->attr & TYPE_FLOAT ) {
++*num_parms;
ins = addr->u.ins;
next = ins->head.next;
while( next->head.opcode != OP_BLOCK ) {
if( _OpIsCall( next->head.opcode ) ) return( FALSE );
if( _OpIsIFunc( next->head.opcode ) ) {
if( FPStkReq( next ) != 0 ) return( FALSE );
}
next = next->head.next;
}
if( _BLOCK( next ) != CurrBlock ) return( FALSE );
}
parm = parm->next;
}
return( TRUE );
}
static void Pushes( instruction *ins ) {
/******************************************/
ins->stk_entry = 0;
ins->stk_exit = 1;
}
static int FPPushImmed( pn parm ) {
/***************************************
Push the list of floating point parameters onto the 8087 stack,
immediately following the definition of each parameter. (Just set
the result of each instruction to ST(0)).
*/
pn next;
an addr;
int parms;
parms = 0;
while( parm != NULL ) {
if( parm->ins != NULL ) {
parm = parm->next;
continue;
}
next = parm->next;
addr = parm->name;
if( addr->tipe->attr & TYPE_FLOAT && HW_COvlap( parm->regs,HW_FLTS ) ){
if( addr->format != NF_INS ) {
_Zoiks( ZOIKS_043 );
}
addr->u.ins->result = AllocRegName( HW_ST0 );
Pushes( addr->u.ins );
parm->ins = addr->u.ins;
addr->format = NF_ADDR;
BGDone( addr );
++parms;
}
parm = next;
}
return( parms );
}
static instruction *PushDelayed( instruction *ins, an addr, call_state *state ) {
/*************************************************************************************
Put the parm "addr" into a temporary, and then add a "push" just
before the call instruction.
*/
ins->result = BGNewTemp( addr->tipe );
if( addr->flags & ADDR_CROSSED_BLOCKS ) {
ins->result->v.usage |= USE_IN_ANOTHER_BLOCK;
}
ins = MakeMove( ins->result, AllocRegName( HW_ST0 ),
TypeClass( addr->tipe ) );
Pushes( ins );
AddIns( ins );
addr->format = NF_ADDR; /* so ins doesn't get freed*/
BGDone( addr );
#if _TARGET & _TARG_80386
if( state->attr & ROUTINE_STACK_RESERVE ) {
ReserveStack( state, ins, addr->tipe->length );
}
#else
state = state;
#endif
return( ins );
}
static bool PushDelayedIfStackOperand( instruction *ins, pn parm, call_state *state ) {
/**************************************************************************************
Delay the "push" of a floating point parameter if any of its
operands are 8087 stack operands.
*/
int i;
an addr;
addr = parm->name;
ins = addr->u.ins;
i = ins->num_operands;
while( --i >= 0 ) {
if( FPIsStack( ins->operands[ i ] ) ) {
parm->ins = PushDelayed( ins, addr, state );
// _Free( parm, sizeof( parm_node ) );
return( TRUE );
}
}
return( FALSE );
}
static bool PushDelayedIfRedefinition( instruction *ins, pn parm, call_state *state ) {
/**************************************************************************************
Delay the "push" of a floating point parameter if any of its
operands are redefined between the calculation of the parm and the
call.
*/
instruction *next;
int i;
next = ins->head.next;
for(;;) {
while( next->head.opcode != OP_BLOCK ) {
i = ins->num_operands;
while( --i >= 0 ) {
if( ReDefinedBy( next, ins->operands[ i ] ) ) {
parm->ins = PushDelayed( ins, parm->name, state );
// _Free( parm, sizeof( parm_node ) );
return( TRUE );
}
}
next = next->head.next;
}
if( _BLOCK( next ) == CurrBlock ) break;
if( _BLOCK( next )->next_block == NULL ) {
next = CurrBlock->ins.hd.next;
} else {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?