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