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