s37index.c

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

C
672
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "conflict.h"
#include "pattern.h"
#include "opcodes.h"
#include "sysmacro.h"
#include "regset.h"
#include "model.h"
#include "cgaux.h"
#include "offset.h"

#include "s37index.def"

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

extern  bool            IsIndexReg(hw_reg_set,type_class_def,bool);
extern  conflict_node   *NameConflict(instruction*,name*);
extern  instruction     *MakeBinary(opcode_defs,name*,name*,name*,type_class_def);
extern  instruction     *MakeUnary(opcode_defs,name*,name*,type_class_def);
extern  name            *AllocAddrConst(name*,int,constant_class,type_class_def);
extern  name            *AllocMemory(pointer,type_length,cg_class,type_class_def);
extern  name            *AllocTemp(type_class_def);
extern  name            *ScaleIndex(name*,name*,type_length,type_class_def,type_length,int,i_flags);
extern  reg_set_index   MarkIndex(instruction*,name*,bool);
extern  void            PrefixIns(instruction*,instruction*);
extern  name            *IndexToTemp(instruction*,name*);
extern  void            NoMemIndex(instruction *);
extern  void            ReplaceOperand(instruction*,name*,name*);
extern  name            *FindIndex(instruction*);
extern  void            TempStrategy(void);
extern  int             FEAttr(sym_handle);
extern  pointer         FEAuxInfo(pointer,int);
extern  name            *AllocRegName(hw_reg_set);
extern  hw_reg_set      GblReg();
extern  instruction     *MakeMove(name*,name*,type_class_def);
extern  name            *AllocIntConst(int);
extern  hw_reg_set      WordReg(int);
extern  void            GetRALN(name*,char*,char*);
extern  offset          AskAddress( label_handle );
extern  label_handle    AskForSymLabel( pointer, cg_class );
extern  void            TellLblBase( label_handle, label_handle, offset );
extern  bool            AskNameROM(pointer,cg_class);
extern  void            SetDataOffsets( offset );




conflict_node *IndexSplit( instruction *ins, name *index ) {
/***********************************************************
*/

    name                *temp;
    conflict_node       *conf;

    temp = IndexToTemp( ins, index );
    conf = NameConflict( ins, temp );
    _SetTrue( conf, INDEX_SPLIT );
    MarkIndex( ins, temp, 0 );
    return( conf );
}


extern  instruction     *NeedIndex( instruction *ins ) {
/*******************************************************
    If any index conflicts are marked as NEEDS_INDEX_SPLIT, split them
    out into a temp as well.
*/

    name                *index;

    index = FindIndex( ins );
    if( index != NULL ) {
        IndexSplit( ins, index );
        ins = ins->head.prev;
    }
    return( ins );
}


static bool LoadingAddress( instruction *ins, name *mem_loc ) {
/**************************************************************
*/
    return( ( ins->head.opcode == OP_LA || ins->head.opcode == OP_CAREFUL_LA )
            && mem_loc != ins->result );
}



extern bool MemNeedsReloc( pointer symbol, cg_class memory_type ) {
/*******************************************
*/
    return( _IsModel( CODE_RENT ) && !AskNameROM( symbol, memory_type ) );
}

struct idx_list  {
    struct idx_list *next;
    name            *idx;
    name            *mem_loc;
    label_handle    label;
};
struct base_temp {
    name             *temp1;   /*initial temp to use */
    struct idx_list  *list;  /* list of index vars to updated */
};

static  struct base_temp   BaseTemp;

static void BaseTempInit(){
    BaseTemp.temp1 = AllocTemp( WD );
    BaseTemp.list = NULL;
}

static void BaseTempAdd( name *idx, label_handle label ){
/******************************************
 Add index var to list that needs base
 Keep in increasing offset
*/
    struct idx_list *cur, **lnk;

    for( lnk = &BaseTemp.list; (cur=*lnk)!=NULL; lnk = &cur->next ){
        if( idx->i.constant <= cur->idx->i.constant )break;
    }
    /* don't add same index twice */
    if( cur == NULL || idx != cur->idx ){
        _Alloc( cur, sizeof( struct idx_list ) );
        cur->idx = idx;
        cur->label = label;
        cur->next = *lnk;
        *lnk = cur;
    }
}

static void BaseTempFini( instruction *start ){
/********************
   Set up a new base temp each time refs go out of range of the current
   temp, replace the index with the new temp.
   prune the list to only each new base temp for fixup after regalloc
*/
    struct idx_list *list, **lnk;
    type_length      cur_addr, disp;
    instruction     *new_ins;
    name            *temp;
    label_handle    base;
    offset          base_offset;

    list = BaseTemp.list;
    if( list != NULL ){
        cur_addr = -4096;
        base = NULL;
        while( list != NULL ){ /* adjust offsets */
            list->mem_loc = list->idx->i.base;
            disp = list->idx->i.constant - cur_addr;
            if( disp > 4095 ){
                temp = AllocTemp( WD );  /* get a base temp */
                cur_addr = list->idx->i.constant;
                base = list->label;
                base_offset = list->mem_loc->v.offset;
            }
            TellLblBase( list->label, base, base_offset );
            list->idx->i.constant -= cur_addr;
            list->idx->i.index  = temp;
            list = list->next;
        }
        lnk = &BaseTemp.list;
        while( (list = *lnk ) != NULL ){
            if( list->idx->i.constant != 0 ){
                *lnk = list->next;
                _Free( list, sizeof( struct idx_list ) );
            }else{
                list->idx = list->idx->i.index;
                new_ins = MakeUnary( OP_LA, list->mem_loc,
                                    list->idx, WD );
                PrefixIns( start, new_ins );
                lnk = &list->next;
            }
        }
    }
}

static void BacktoConst( struct idx_list *what ){
/*************************************
  Find all occurances of temp and replace with a =A(base)
*/
    block       *blk;
    instruction *ins;

    blk = HeadBlock;
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            SettoACon( ins, what  );
            ins = ins->head.next;
        }
        blk = blk->next_block;
    }
}

static  void    SettoACon( instruction *ins, struct idx_list  *what ) {
/**********************************************
    find any refs to temp and replace with a constant
*/

    int         i;
    name        *temp;
    name        *con;

    temp = what->idx;
    con = AllocAddrConst( what->mem_loc, 0, CONS_ADDRESS, WD );
    i = ins->num_operands;
    while( --i >= 0 ) {
        if( ins->operands[ i ] == temp ) {
            ins->operands[ i ] = con;
        }
    }
    if( ins->result == temp ){
    /* a zoiks ? */
    }
}

extern void MemtoBaseTemp( void ){
/********************************
    change memrefs to an index off a temp loaded with
    an address in range of the 4k barrier ieee!
*/
    instruction *ins;
    block       *blk;

    blk = HeadBlock;
    SetDataOffsets( 0 ); /* set offsets for fixed data */
    BaseTempInit();
    while( blk != NULL ) {
        ins = blk->ins.hd.next;
        while( ins->head.opcode != OP_BLOCK ) {
            ins = NoMemRefs( ins )->head.next;
        }
        blk = blk->next_block;
    }
    blk = HeadBlock;
    BaseTempFini( blk->ins.hd.next );
}


void FixMemBases( void ){
/****************************
    replace any base temp that didn't make it to a reg with an acon
*/
    struct idx_list *list, *old;
    name   *temp;

    list = BaseTemp.list;
    while( list != NULL ){
        temp = list->idx;
        if( temp->v.usage & USE_MEMORY ){
            BacktoConst( list );
        }
        old = list;
        list = list->next;
        _Free( old, sizeof( struct idx_list ) );
    }
}

static name *RepMemWithOffset(  name * mem_loc ) {
/*************************************************
    If "mem_loc" can be based off a global temp do so
    by using BaseTemp sorry about the static I'll fix it later
*/
    name               *new_idx;
    i_flags             flags;
    label_handle        label;
    unsigned  long int  addr;

    label = AskForSymLabel( mem_loc->v.symbol, mem_loc->m.memory_type );
    addr = AskAddress( label );
    if( addr != -1 ){
        flags = X_FAKE_BASE | X_BASE_IS_INDEX;
        if( mem_loc->v.usage & VAR_VOLATILE ) {
            flags |= X_VOLATILE;
        }
        addr += mem_loc->v.offset;
        new_idx = ScaleIndex( BaseTemp.temp1, mem_loc, addr,
                           mem_loc->n.name_class,
                          mem_loc->n.size, 0, flags );
        BaseTempAdd( new_idx, label );
    }else{
        new_idx = NULL;
    }
    return( new_idx );
}

static  name   *RepAux( name * mem_loc ) {
/********************************************************************
    If "mem_loc" is a global reg based var turn into offset( reg )
*/
    name                *new_idx;
    fe_attr             attr;
    int                 offset;
    i_flags             flags;

    attr = 0;
    offset = -1;
    if( mem_loc->m.memory_type == CG_FE && mem_loc->v.symbol != NULL ) {
        attr = FEAttr( mem_loc->v.symbol );

⌨️ 快捷键说明

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