i87opt.c

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

C
906
字号
#endif
    }
    return( BackUpAndFree( ins, ins, next ) );
}


static  instruction    *Opt87Sequence( instruction *ins, bool *again ) {
/************************************************************************
    Look for silly 8087 sequences and fix them up.
*/

    instruction         *next;
    instruction         *third;
    instruction         *ret;
    type_class_def      class;
    int                 num_ops;

    next = Next87Ins( ins );
    ret = ins->head.next;
    if( next == ins ) return( ret );
    if( G( ins ) == G_RFLD && FPRegNum( ins->operands[ 0 ] ) == 0 ) {
        if( G( next ) == G_MFST ) {

            /* FLD ST, FSTP X ===> FST X */

            FreeIns( ins );
            if( FPResultNotNeeded( next ) ) {
                ret = BackUpAndFree( ins, next, NULL );
            } else {
                ret = next;
                NoPop( next );
            }
            *again = TRUE;
        } else if( G( next ) == G_RFST ) {

            /* FLD ST, FSTP ST(i) ===> FST ST(i-1) */

            if( FPRegNum( next->result ) == 0 ) {
                ret = BackUpAndFree( ins, ins, next );
            } else {
                AdjustST( &next->result, -1 );
                FreeIns( ins );
                ret = next;
                NoPop( next );
            }
            *again = TRUE;
        } else if( G( next ) == G_RNFBINP || G( next ) == G_RRFBINP ) {

            /* FLD ST, FopP ST(i),ST ==> Fop ST(i-1),ST */
            if( FPRegNum( next->operands[ 0 ] ) == 0 ) {
                ret = BackUpAndFree( ins, ins, next );
            } else {
                AdjustST( &next->operands[ 0 ], -1 );
                NoPopRBin( next );
                FreeIns( ins );
                ret = next;
            }
            *again = TRUE;
        } else if( G( next ) == G_FXCH && FPRegNum( next->result ) == 1 ) {
            FreeIns( next );
            *again = TRUE;
            ret = ins;
        }
    } else if( G( ins ) == G_RFLD || G( ins ) == G_MFLD ) {
        if( ( G( next ) == G_RRFBINP || G( next ) == G_RNFBINP ) ) {
            if( G( ins ) == G_MFLD ) {
                class = ins->operands[ 0 ]->n.name_class;
                if( !_IsFloating( class ) ) return( ret ); /* need convert! */
            }
            if( ( FPRegNum( next->operands[ 0 ] ) == 1 ) ) {

                /* FLD X, FxxP ST(1) ==> Fxx X */

                next->result = ST( 0 );
                next->operands[ 0 ] = ins->operands[ 0 ];
                num_ops = NumOperands( ins );
                if( ins->num_operands > num_ops
                 && next->num_operands <= NumOperands( next ) ) {
                    next->operands[ next->num_operands ]
                                     = ins->operands[ num_ops ];
                    next->num_operands++;
                }
                FreeIns( ins );
                NoPopBin( next );
                *again = TRUE;
                ret = next;
            }
        } else if( G( next ) == G_RFLD || G( next ) == G_MFLD ) {
            if( G( ins ) == G_MFLD && G( next ) == G_MFLD &&

                /* FLD X, FLD X ==> FLD X, FLD ST(0) */

                ins->operands[0] == next->operands[0] ) {
                next->operands[0] = ST( 0 );
                ToRFld( next );
                *again = TRUE;
                ret = next;
            } else {

                /* FLD X, FLD Y, FXCH ST(1) ==> FLD Y, FLD X */
                third = Next87Ins( next );
                if( third == next ) return( ret );
                if( G( third ) == G_FXCH && FPRegNum( third->result ) == 1 ) {
                    FreeIns( third );
                    if( FPRegNum( next->operands[0] ) != 0 ) {
                        ins->head.next->head.prev = ins->head.prev;
                        ins->head.prev->head.next = ins->head.next;
                        SuffixIns( next, ins );
                        if( G( ins ) == G_RFLD ) {
                            AdjustST( &ins->operands[0], +1 );
                        }
                        if( G( next ) == G_RFLD ) {
                            AdjustST( &next->operands[0], -1 );
                        }
                        ret = next;
                    } else {
                        ret = ins;
                    }
                    *again = TRUE;
                }
            }
        } else if( G( ins ) == G_MFLD ) {
            if( G( next ) == G_MFST ) {
                if(ins->operands[0]->n.name_class==next->result->n.name_class) {
                    ret = To86Move( ins, next );
                }
            } else if( G( next ) == G_MRFBIN || G( next ) == G_MNFBIN ) {
                if( ins->operands[0] == next->operands[ 0 ] ) {

                    /* FLD X, FOP X ==> FLD X, FOP ST */

                    next->operands[ 0 ] = ST( 0 );
                    DelSeg( next );
                    NoMemBin( next );
                    *again = TRUE;
                    ret = ins;
                }
            }
        }
    } else if( G( ins ) == G_MFST || G( ins ) == G_RFST ) {
        if( G( next ) == G_MFLD
        && ( next->operands[ 0 ] == ins->result )
        &&   _IsFloating( ins->result->n.name_class )
        && !IsVolatile( ins->result ) ) {

            /* FSTP X, FLD X ==> FST X */

            FreeIns( next );
            if( FPResultNotNeeded( ins ) ) {
                ret = BackUpAndFree( ins, ins, NULL );
            } else {
                ret = ins;
                NoPop( ins );
            }
            *again = TRUE;
        } else if( G( next ) == G_RFLD
             && FPRegNum( next->operands[0] ) + 1 == FPRegNum( ins->result ) ) {

            /* FSTP ST(i), FLD ST(i-1) ==> FST ST(i) */

            FreeIns( next );
            NoPop( ins );
            *again = TRUE;
            ret = ins;
        }
    } else if( G( ins ) == G_FXCH ) {
        if( G( next ) == G_FXCH ) {

            /* FXCH ST(i) FXCH ST(i) => nothing */

            if( FPRegNum( ins->result ) == FPRegNum( next->result ) ) {
                FreeIns( next );
                next = BackUpAndFree( ins, ins, NULL );
                *again = TRUE;
                ret = next;
            }
        } else {
            if( G( next ) == G_RRFBINP || G( next ) == G_RNFBINP ) {

                if( FPRegNum( ins->result ) == FPRegNum( next->operands[0] ) ) {

                    /* FXCH ST(i), FopP ST(i),ST -> FopRP ST(i),ST */
                    FreeIns( ins );
                    ReverseFPGen( next );
                    *again = TRUE;
                    ret = next;
                }
            }
        }
    } else if( G( ins ) == G_MFSTNP ) {
        if( G( next ) == G_MFLD && ins->result == next->operands[0] ) {

            /* FST X, FLD X => FST X, FLD ST */

            next->operands[0] = ST( 0 );
            ToRFld( next );
            *again = TRUE;
            ret = ins;
        } else if( RedundantStore( ins ) ) {
            ret = BackUpAndFree( ins, ins, NULL );
            *again = TRUE;
        }
    } else if( G( ins ) == G_RNFBIN || G( ins ) == G_RRFBIN ) {
        if( G( next ) == G_RFST && next->result == ins->operands[0] ) {
            ToPopBin( ins );
            FreeIns( next );
            *again = TRUE;
            ret = ins;
        }
    }
    return( ret );
}


static  void    MoveThrough( name *from, name *to, instruction *from_ins,
                             instruction *to_ins, name *reg,
                             type_class_def class ) {
/****************************************************
    Move from "from" to "to" using register name "reg". Segments if
    any should be taken from "from_ins" and "to_ins".
*/

    bool        dummy;
    instruction *new;

    new = MakeMove( from, reg, class );
    new->u.gen_table = FindGenEntry( new, &dummy );
    DupSeg( from_ins, new );
    PrefixIns( to_ins, new );
    new = MakeMove( reg, to, class );
    DupSeg( to_ins, new );
    new->u.gen_table = FindGenEntry( new, &dummy );
    PrefixIns( to_ins, new );
}

extern  bool    DivIsADog( type_class_def class )
/***********************************************/
{

    return( _FPULevel( FPU_87 ) && _IsFloating( class ) );
}

extern  void    Opt8087( void ) {
/**************************
    Look for silly 8087 sequences and change them into better ones.
*/

    block       *blk;
    instruction *ins;
    int         i;
    bool        again;

    blk = HeadBlock;
    while( blk != NULL ) {
        i = 0;
        for( ins = blk->ins.hd.next;
             ins->head.opcode != OP_BLOCK; ins = ins->head.next ) {
            ins->sequence = ++i;
        }
        ins = blk->ins.hd.next;
        again = FALSE;
        while( ins->head.opcode != OP_BLOCK ) {
            if( _GenIs8087( ins->u.gen_table->generate ) ) {
                if( !FSinCos( ins ) ) {
                    ins = Opt87Sequence( ins, &again );
                } else {
                    ins = ins->head.next;
                }
            } else {
                ins = ins->head.next;
            }
        }
        if( !again ) {
            for( ins = blk->ins.hd.next;
                 ins->head.opcode != OP_BLOCK; ins = ins->head.next ) {
                if( FPResultNotNeeded( ins ) ) {
                    ins->result = ST( 0 );
                    ToRFstp( ins );
                }
            }
            blk = blk->next_block;
        }
    }
}

extern  void    FixP5Divs( void ) {
/*********************************/

    block       *blk;
    instruction *ins;

    if( !_IsTargetModel( P5_DIVIDE_CHECK ) ) return;
    if( !_FPULevel( FPU_87 ) ) return;
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        for( ins = blk->ins.hd.next; ins->head.opcode != OP_BLOCK; ins = ins->head.next ) {
            if( ins->head.opcode != OP_DIV ) continue;
            if( !_IsFloating( ins->type_class ) ) continue;
            ins->head.opcode = OP_P5DIV;
        }
    }
}

⌨️ 快捷键说明

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