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