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