i86index.c

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

C
519
字号
                                    index->i.index_flags | X_SEGMENTED );
            if( ins->result == index ) {
                ins->result = new_index;
            }
            i = ins->num_operands;
            while( --i >= 0 ) {
                if( ins->operands[ i ] == index ) {
                    ins->operands[ i ] = new_index;
                }
            }
            *seg_ptr = SegmentPart( index->i.index );
            MarkSegment( ins, *seg_ptr );
            ins->num_operands++;
        }
        if( conf != NULL ) {
            _SetTrue( conf, SEGMENT_SPLIT );
        }
    }
}

extern  void    FixMemRefs( void ) {
/*****************************
    Make sure that no N_MEMORY names are used as indecies.  This would
    cause problems since we might need a segment override for the INDEX
    as well as the memory which we're indexing to get to.  This is no
    good since each instruction can only have one segment override,
    hence one memory reference.
*/

    block       *blk;
    instruction *ins;

    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
        #if _TARGET & _TARG_80386
            ExpandThreadDataRef( ins );
        #endif
            NoMemIndex( ins );
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
}


extern  void    FixSegments( void ) {
/******************************
    Add segment overrides to any instruction in the routine that needs
    them.
*/

    block       *blk;
    instruction *ins;

    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            AddSegment( ins );
            /* Generate an error if segment override is requested and all segment
             * registers are pegged. However we do NOT want to generate an error
             * if this is a CS override in flat model - that particular case is not
             * an error because the CS override is essentially a no-op.  MN
             */
#define ANY_FLOATING (FLOATING_DS|FLOATING_ES|FLOATING_FS|FLOATING_GS)
            if( _IsntTargetModel( ANY_FLOATING ) &&
                ins->num_operands > NumOperands( ins )
            #if _TARGET & _TARG_80386
                 && !(_IsTargetModel( FLAT_MODEL ) &&
                (ins->operands[ ins->num_operands-1 ]->n.class == N_REGISTER) &&
                HW_CEqual( ins->operands[ ins->num_operands-1 ]->r.reg, HW_CS ))
            #endif
            ) {
                /* throw away override */
                ins->num_operands--;
                FEMessage( MSG_NO_SEG_REGS, AskForLblSym( CurrProc->label ) );
            }
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
}


static  type_class_def  FltClass( instruction *ins ) {
/*****************************************************
    return the floating point class (FD or FS) of "ins", or XX if it
    does not involve floating point.
*/

    if( _IsFloating( ins->type_class ) ) return( ins->type_class );
    if( _IsFloating( _OpClass( ins ) ) ) return( _OpClass( ins ) );
    return( XX );
}

extern  void    MergeIndex( void ) {
/*****************************
    Merge segment overrides back into the index registers.  This is
    called just before scoreboarding to simplify matters.  For example
    MOV  [DI], ES => AX becomes MOV [ES:DI] => AX.
*/

    block       *blk;
    instruction *ins;
    int         i;
    name        **name;
    bool        dec;

    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            i = NumOperands( ins );
            if( i < ins->num_operands ) {
                dec = FALSE;
                while( --i >= 0 ) {
                    name = &ins->operands[ i ];
                    if( (*name)->n.class == N_INDEXED ) {
                        Merge( name, ins );
                        dec = TRUE;
                    }
                }
                if( ins->result != NULL ) {
                    name = &ins->result;
                    if( (*name)->n.class == N_INDEXED ) {
                        Merge( name, ins );
                        dec = TRUE;
                    }
                }
                if( dec ) {
                    ins->num_operands--;
                }
            }
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
}

static  void    Merge( name **pname, instruction *ins ) {
/********************************************************
    called by MergeIndex ^
*/

    name        *index;
    name        *reg;
    hw_reg_set  tmp;

    index = *pname;
    tmp = index->i.index->r.reg;
    HW_TurnOn( tmp, ins->operands[ ins->num_operands-1 ]->r.reg );
    reg = AllocRegName( tmp );
    *pname = ScaleIndex( reg, index->i.base, index->i.constant,
                         index->n.name_class, index->n.size,
                         index->i.scale, index->i.index_flags );
}


extern  void    FixChoices( void ) {
/*****************************
    Run through the conflict list and make sure that no conflict is
    allowed to get cached in a segment register unless it was actually
    used as a segment override somewhere in the program.  This avoids
    loads of bad selectors in protected mode.
*/

    conflict_node       *conf;
    name                *temp;
    name                *alias;

    PropSegments();
    conf = ConfList;
    while( conf != NULL ) {
        if( _Isnt( conf, VALID_SEGMENT ) ) {
            conf->possible = NoSegments( conf->possible );
            temp = conf->name;
            if( temp->n.class == N_TEMP ) {
                alias = temp;
                for(;;) {
                    alias = alias->t.alias;
                    alias->t.possible = NoSegments( alias->t.possible );
                    if( alias == temp ) break;
                }
            }
        }
        conf = conf->next_conflict;
    }
}

static  void    PropSegments( void ) {
/*******************************
    For every instruction of the form MOV X => Y, mark the conflict node
    for X as a valid segment if the conflict for Y is marked as a valid
    segment.
*/

    block               *blk;
    instruction         *ins;
    conflict_node       *src;
    conflict_node       *dst;
    bool                change;

    src = ConfList;
    while( src != NULL ) {
        if( _Is( src, VALID_SEGMENT ) ) {
            _SetTrue( src, WAS_SEGMENT );
        }
        src = src->next_conflict;
    }
    for(;;) {
        change = FALSE;
        blk = HeadBlock;
        while( blk != NULL ) {
            ins = blk->ins.hd.prev;
            while( ins->head.opcode != OP_BLOCK ) {
                if( ins->head.opcode == OP_MOV ) {
                    dst = NameConflict( ins, ins->result );
                    if( dst != NULL && _Is( dst, WAS_SEGMENT ) ) {
                        src = NameConflict( ins, ins->operands[ 0 ] );
                        if( src != NULL && _Isnt( src, WAS_SEGMENT ) ) {
                            _SetTrue( src, WAS_SEGMENT );
                            change = TRUE;
                        }
                    }
                }
                ins = ins->head.prev;
            }
            blk = blk->next_block;
        }
        if( change == FALSE ) break;
    }
}


extern  void    FixFPConsts( instruction *ins ) {
/************************************************
    Fix floating point constants, by forcing them into memory if they
    are not going to be segment register addressable.  This is done so that
    OneMemRef, the routine that ensures that we will have only one
    memory reference, (therefore one segment override), will see it as a
    memory reference and treat it accordingly.
*/

    int                 i;
    type_class_def      class;

    if( !FPCInCode() && (_IsTargetModel( FLOATING_SS ) && _IsTargetModel( FLOATING_DS )) ) {
        class = FltClass( ins );
        if( class != XX ) {
            i = ins->num_operands;
            while( --i >= 0 ) {
                ins->operands[ i ] = Addressable( ins->operands[ i ], class );
            }
        }
    }
}

⌨️ 快捷键说明

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