s37index.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 672 行 · 第 1/2 页
C
672 行
}
if( !( attr & FE_PROC ) && ( attr & (FE_IMPORT|FE_GLOBAL) ) ) {
offset = (int)FEAuxInfo( FEAuxInfo( mem_loc->v.symbol, AUX_LOOKUP ),
AUX_OFFSET );
}
if( offset != -1 ) {
flags = X_FAKE_BASE;
if( mem_loc->v.usage & VAR_VOLATILE ) {
flags |= X_VOLATILE;
}
new_idx = ScaleIndex( AllocRegName( GblReg() ), mem_loc, offset,
mem_loc->n.name_class, mem_loc->n.size,
0, flags );
}else{
new_idx = NULL;
}
return( new_idx );
}
static name *RepRelocMem( instruction * ins, name * mem_loc ) {
/********************************************************************
"mem_loc" is a relative mem location add in global base reg.
*/
name *new_idx;
name *temp;
instruction *new_ins;
i_flags flags;
flags = X_FAKE_BASE;
if( mem_loc->v.usage & VAR_VOLATILE ) {
flags |= X_VOLATILE;
}
temp = AllocTemp( WD );
new_ins = MakeUnary( OP_CAREFUL_LA, mem_loc, temp, WD );
PrefixIns( ins, new_ins );
new_ins = MakeBinary( OP_ADD, temp, AllocRegName( GblReg() ),
temp, WD );
PrefixIns( ins, new_ins );
if( LoadingAddress( ins, mem_loc ) ) {
ins->head.opcode = OP_CONVERT;
ins->base_type_class = WD;
new_idx = temp;
} else {
new_idx = ScaleIndex( temp, mem_loc, 0, mem_loc->n.name_class,
mem_loc->n.size, 0, flags );
}
return( new_idx );
}
static instruction *MemToIndex( instruction * ins, name * mem_loc ) {
/************************************************************************
Turn memory reference "mem_loc" in "ins" into a LA MEM_LOC => temp
and use [temp] instead. This matches the 370 addressing modes more
closely, and allows the register allocator to the these address
constants in registers. This also takes care of variables named in
aux files, by changing them into references like 100(,10). Finally,
when the RENT option is turned on, non-constant references are changed
into LA MEM_LOC => temp, ADD temp, 10 => temp
*/
name *temp;
name *new_idx;
instruction *new_ins;
i_flags flags;
flags = X_FAKE_BASE;
if( mem_loc->v.usage & VAR_VOLATILE ) {
flags |= X_VOLATILE;
}
if( (new_idx = RepAux( mem_loc )) != NULL ){
ReplaceOperand( ins, mem_loc, new_idx );
}else if( (new_idx = RepMemWithOffset( mem_loc )) != NULL ){
ReplaceOperand( ins, mem_loc, new_idx );
}else if( MemNeedsReloc( mem_loc->v.symbol, mem_loc->m.memory_type ) ) {
new_idx = RepRelocMem( ins, mem_loc );
ReplaceOperand( ins, mem_loc, new_idx );
} else {
if( LoadingAddress( ins, mem_loc ) ){
ins = NULL;
}else{
temp = AllocTemp( WD );
new_ins = MakeUnary( OP_CAREFUL_LA, mem_loc, temp, WD );
new_idx = ScaleIndex( temp, mem_loc, 0, mem_loc->n.name_class,
mem_loc->n.size, 0, flags );
PrefixIns( ins, new_ins );
ReplaceOperand( ins, mem_loc, new_idx );
}
}
return( ins );
}
static void AddBaseIndex( instruction * ins, name * index ) {
/****************************************************************
When we have an N_INDEXED name "index" in "ins" of the form X[y],
where X is N_MEMORY or N_TEMP, we need to change it into an
LEA X => temp if you just use addr const load then need
code for AUX & rent
ADD temp+y =>temp
and use [temp] instead, since the 370 cannot handle
complex addressing modes.
*/
name *temp;
instruction *new_ins;
name *new_idx;
name *iname;
type_class_def class;
i_flags flags;
temp = AllocTemp( WD );
new_ins = MakeUnary( OP_LA, index->i.base, temp, WD );
PrefixIns( ins, new_ins );
iname = index->i.index;
class = iname->n.name_class;
new_idx = AllocTemp( class );
new_ins = MakeBinary( OP_ADD, temp, iname, new_idx, PT );
PrefixIns( ins, new_ins );
flags = index->i.index_flags;
flags |= X_FAKE_BASE;
new_idx = ScaleIndex( new_idx, index->i.base,
index->i.constant, index->n.name_class,
index->n.size, index->i.scale,
flags );
ReplaceOperand( ins, index, new_idx );
}
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;
conflict_node *conf;
name = index->i.index;
if( name->n.class == N_REGISTER ) {
return( IsIndexReg( name->r.reg, name->n.name_class, 0 ) );
}
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, 0 );
return( TRUE );
}
}
static instruction *NoMemRefs( instruction *ins ) {
/*******************************************************
Get rid of all direct memory references in "ins" since the 370 can't
handle them. We need to load =A(x) or =V(x) or use the global
register (10) instead.
*/
int i;
name *mem_loc;
instruction *last_ins;
last_ins = ins;
for( ;; ) {
i = ins->num_operands;
mem_loc = NULL;
while( --i >= 0 ) {
if( ins->operands[ i ]->n.class == N_MEMORY ) {
mem_loc = ins->operands[ i ];
}
}
if( ins->result != NULL ) {
if( ins->result->n.class == N_MEMORY ) {
mem_loc = ins->result;
}
}
if( mem_loc == NULL ) break;
ins = MemToIndex( ins, mem_loc );
if( ins == NULL ) break;
last_ins = ins;
}
return( last_ins );
}
extern void FixCallIns( instruction *ins ) {
/*******************************************
Make the L LN,=A(routine) explicit for all call instructions so that
the constant can get cached in registers.
*/
char ra,ln;
name *routine;
name *reg;
name *used;
hw_reg_set tmp;
instruction *new_ins;
if( ins->head.opcode != OP_CALL ) return;
routine = ins->operands[CALL_OP_ADDR];
GetRALN( routine, &ra, &ln );
reg = AllocRegName( WordReg( ln ) );
new_ins = MakeUnary( OP_LA, routine, reg, WD );
HW_Asgn( tmp, ins->operands[CALL_OP_USED]->r.reg );
HW_TurnOn( tmp, reg->r.reg );
used = AllocRegName( tmp );
ins->operands[CALL_OP_USED] = used;
ins->operands[CALL_OP_USED2] = used;
PrefixIns( ins, new_ins );
}
static void NoMemBase( instruction *ins ) {
/**********************************************
Make sure that no N_INDEXED names has a base field, since cannot be
generated using 370 addressing modes.
*/
int i;
name *bad_index;
name *op;
if( ins->head.opcode == OP_SELECT ) return;
for( ;; ) {
i = ins->num_operands;
bad_index = NULL;
while( --i >= 0 ) {
op = ins->operands[ i ];
if( op->n.class == N_INDEXED ) {
if( HasTrueBase( op ) ) {
bad_index = op;
}
}
}
op = ins->result;
if( op != NULL ) {
if( op->n.class == N_INDEXED ) {
if( HasTrueBase( op ) ) {
bad_index = op;
}
}
}
if( bad_index == NULL ) break;
(void)AddBaseIndex( ins, bad_index );
}
}
extern void FixSegments() {
/******************************
stub for 8086 version
*/
}
extern void FixMemRefs() {
/*****************************
Make sure that all memory references are broken up into things that
we can handle using 370 addressing modes.
*/
block *blk;
instruction *ins;
blk = HeadBlock;
while( blk != NULL ) {
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
NoMemIndex( ins );
ins = ins->head.next;
}
blk = blk->next_block;
}
blk = HeadBlock;
while( blk != NULL ) {
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
NoMemBase( ins );
ins = ins->head.next;
}
blk = blk->next_block;
}
blk = HeadBlock;
while( blk != NULL ) {
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
FixCallIns( ins );
ins = ins->head.next;
}
blk = blk->next_block;
}
TempStrategy();
}
extern void FixChoices() {
/*****************************
stub for 8086 version.
*/
}
extern bool LoadAToMove( instruction *ins ) {
/************************************************
Turn a load address instruction into MOV =A(X) => foo
*/
name *op;
if( ins->head.opcode != OP_LA && ins->head.opcode != OP_CAREFUL_LA ) {
return( FALSE );
}
op = ins->operands[ 0 ];
if( op->n.class != N_MEMORY ) return( FALSE );
ins->head.opcode = OP_MOV;
ins->operands[ 0 ] = AllocAddrConst( op, 0, CONS_ADDRESS, WD );
return( TRUE );
}
extern void FixFPConsts( instruction *ins ) {
/************************************************
stub for 8087
*/
ins = ins;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?