i86index.c

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

C
519
字号
/****************************************************************************
*
*                            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:  Intel x86 indexed addressing instruction processing.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "procdef.h"
#include "conflict.h"
#include "pattern.h"
#include "opcodes.h"
#include "sysmacro.h"
#include "regset.h"
#include "model.h"
#include "feprotos.h"

extern proc_def             *CurrProc;
extern  block               *HeadBlock;
extern  conflict_node       *ConfList;
extern  opcode_defs         String[];

extern  bool            IsIndexReg(hw_reg_set,type_class_def,bool);
extern  bool            SegOver(name*);
extern  conflict_node   *NameConflict(instruction*,name*);
extern  instruction     *MakeMove(name*,name*,type_class_def);
extern  name            *Addressable(name*,type_class_def);
extern  name            *AllocRegName(hw_reg_set);
extern  name            *AllocTemp(type_class_def);
extern  name            *FindIndex(instruction*);
extern  name            *GetSegment(name*);
extern  name            *NearSegment(void);
extern  name            *OffsetPart(name*);
extern  name            *ScaleIndex(name*,name*,type_length,type_class_def,type_length,int,i_flags);
extern  name            *SegmentPart(name*);
extern  reg_set_index   MarkIndex(instruction*,name*,bool);
extern  reg_set_index   NoSegments(reg_set_index);
extern  void            MarkSegment(instruction*,name*);
extern  void            NoMemIndex(instruction*);
extern  void            PrefixIns(instruction*,instruction*);
extern  int             NumOperands(instruction*);
extern  name            *IndexToTemp(instruction*,name*);
extern  name            *FindIndex(instruction*);
extern  bool            FPCInCode( void );
extern  sym_handle      AskForLblSym(label_handle);
extern  void            ExpandThreadDataRef(instruction*);

static  void            Merge( name **pname, instruction *ins );
static  void            PropSegments(void);

extern  instruction     *NeedIndex( instruction *ins ) {
/*******************************************************
    Mark conflicts for any name used in instruction as as segment as
    NEEDS_SEGMENT, or split out the segment if it is marked as
    NEEDS_SEGMENT_SPLIT (move the segment operand to a temp and use the
    temp as the segment override).  Also, if any index conflicts are
    marked as NEEDS_INDEX_SPLIT, split them out into a temp as well.
*/

    name                *temp;
    name                *index;
    conflict_node       *conf;
    name                *name;

    if( ins->num_operands > NumOperands( ins ) ) {
        name = ins->operands[ ins->num_operands-1 ];
        conf = NameConflict( ins, name );
        if( conf != NULL && _Isnt( conf, NEEDS_SEGMENT_SPLIT ) ) {
            _SetTrue( conf, NEEDS_SEGMENT );
            MarkSegment( ins, name );
        } else if( name->n.class != N_REGISTER ) {
            if( conf != NULL ) {
                _SetFalse( conf, NEEDS_SEGMENT );
                _SetTrue( conf, WAS_SEGMENT );
            }
            temp = AllocTemp( U2 );
            ins->operands[ ins->num_operands-1 ] = temp;
            PrefixIns( ins, MakeMove( name, temp, U2 ) );
            MarkSegment( ins, temp );
            _SetTrue( NameConflict( ins, temp ), SEGMENT_SPLIT );
            ins = ins->head.prev;
        }
    }
    index = FindIndex( ins );
    if( index != NULL ) {
        temp = IndexToTemp( ins, index );
        conf = NameConflict( ins, temp );
        _SetTrue( conf, INDEX_SPLIT );
        if( HasTrueBase( index ) && index->i.base->n.class == N_TEMP ) {
            MarkIndex( ins, temp, TRUE );
        } else {
            MarkIndex( ins, temp, FALSE );
        }
        ins = ins->head.prev;
    }
    return( ins );
}


extern  bool    IndexOkay( instruction *ins, name *index ) {
/***********************************************************
    return TRUE if "index" needs to be split out of instruction and a
    short lived temporary used instead.
*/

    name                *name;
    bool                is_temp_index;
    conflict_node       *conf;

    if( HasTrueBase( index ) && index->i.base->n.class == N_TEMP ) {
        is_temp_index = TRUE;
    } else {
        is_temp_index = FALSE;
    }
    name = index->i.index;
    if( ins->table == (struct opcode_entry *)String ) return( TRUE );
    if( name->n.class == N_REGISTER ) {
        return( IsIndexReg( name->r.reg, name->n.name_class, is_temp_index ) );
    }
/* The next two lines require some explanation. If there is a CP/PT
   index still hanging around, it is because a reduction routine
   created it, so it can be handled. Normally, all CP/PT indecies are broken
   up into seg:foo[offset] before we ever get to register allocation */
    if( name->n.name_class == CP ) return( TRUE );
    if( name->n.name_class == PT ) return( TRUE );
    if( name->v.conflict == NULL ) return( FALSE );
    if( name->v.usage & USE_MEMORY ) return( FALSE );
    if( name->n.class != N_TEMP ) return( FALSE );
    conf = NameConflict( ins, name );
    if( conf == NULL ) return( FALSE );
    if( _Is( conf, NEEDS_INDEX_SPLIT ) ) {
        _SetFalse( conf, NEEDS_INDEX );
        return( FALSE );
    } else {
        _SetTrue( conf, NEEDS_INDEX );
        ins->head.state = OPERANDS_NEED_WORK;
        ins->t.index_needs = MarkIndex( ins, name, is_temp_index );
        return( TRUE );
    }
}


static  bool    SegIsBase( name **index ) {
/******************************************
    return TRUE if the segment override for N_INDEXED "*index" is the
    same as the segment override for its N_MEMORY base location, and if
    it is, change *index to point to the N_MEMORY base location.
*/

    if( (*index)->n.class == N_MEMORY ) return( TRUE );
    if( (*index)->i.index->n.size == WORD_SIZE ) {
        (*index) = (*index)->i.base;
        return( TRUE );
    }
    return( FALSE );
}

static  name    *FindSegment( instruction *ins ) {
/*************************************************
    return a pointer to a name within "ins" which requires a segment
    override but does not already have one.
*/

    name        *index;
    int         i;

    if( ins->num_operands > NumOperands( ins ) ) return( NULL );
    if( ins->type_class == XX ) {
        if( ins->head.opcode != OP_CALL_INDIRECT ) {
            if( ins->head.opcode != OP_PUSH ) return( NULL );
            /* careful ... this assumes small pushes split not movsb'd */
            /* see i86split */
            if( ins->operands[ 0 ]->n.size > 4*WORD_SIZE ) return( NULL );
        }
    }
    i = ins->num_operands;
    if( ins->head.opcode != OP_LA && ins->head.opcode != OP_CAREFUL_LA ) {
        while( --i >= 0 ) {
            index = ins->operands[ i ];
            if( SegOver( index ) ) return( index );
        }
    }
    if( ins->result != NULL && SegOver( ins->result ) ) return( ins->result );
    return( NULL );
}


extern  void    AddSegment( instruction *ins ) {
/***********************************************
    Look at instruction "ins" and if any of its operands need a segment
    override, add it to the instruction as an extra operand.
*/

    int                 i;
    name                *index;
    name                *new_index;
    instruction         *new_ins;
    name                **seg_ptr;
    name                *seg;
    conflict_node       *conf;


    index = FindSegment( ins );
    conf = NULL;
    if( index != NULL ) {
        seg_ptr = &ins->operands[ ins->num_operands ];
        if( SegIsBase( &index ) ) {
            if( index != NULL ) {
                seg = GetSegment( index );
                if( seg->n.class != N_REGISTER ) {
                    new_ins = MakeMove( seg, AllocTemp( U2 ), U2 );
                    *seg_ptr = new_ins->result;
                    ins->num_operands++;
                    PrefixIns( ins, new_ins );
                    MarkSegment( ins, *seg_ptr );
                    conf = NameConflict( new_ins, *seg_ptr );
                }
            } else {
                *seg_ptr = NearSegment();
                ins->num_operands++;
                if( (*seg_ptr)->n.class == N_CONSTANT ) {
                    new_ins = MakeMove( *seg_ptr, AllocTemp( U2 ), U2 );
                    *seg_ptr = new_ins->result;
                    PrefixIns( ins, new_ins );
                    MarkSegment( ins, *seg_ptr );
                    conf = NameConflict( new_ins, *seg_ptr );
                }
            }
        } else { /* segment is the high part of the index */
            new_index = ScaleIndex( OffsetPart( index->i.index ),
                                    index->i.base,
                                    index->i.constant,
                                    index->n.name_class,
                                    index->n.size,
                                    index->i.scale,

⌨️ 快捷键说明

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