rscsplit.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,383 行 · 第 1/4 页
C
1,383 行
break;
case N_REGISTER:
if( class == U1 || class == I1 ) {
new = AllocRegName( Low16Reg( tosplit->r.reg ) );
} else if( class == U2 || class == I2 ) {
new = AllocRegName( Low32Reg( tosplit->r.reg ) );
} else {
new = AllocRegName( Low64Reg( tosplit->r.reg ) );
}
break;
case N_TEMP:
new = TempOffset( tosplit, 0, class );
if( new->t.temp_flags & CONST_TEMP ) {
name *cons = tosplit->v.symbol;
if( tosplit->n.name_class == FD ) {
cons = Int64Equivalent( cons );
}
new->v.symbol = LowPart( cons, class );
}
break;
case N_MEMORY:
new = AllocMemory( tosplit->v.symbol, tosplit->v.offset,
tosplit->m.memory_type, class );
new->v.usage = tosplit->v.usage;
break;
case N_INDEXED:
new = ScaleIndex( tosplit->i.index, tosplit->i.base,
tosplit->i.constant, class,
0, tosplit->i.scale, tosplit->i.index_flags );
break;
}
return( new );
}
extern name *HighPart( name *tosplit, type_class_def class )
/***************************************************************
* Return the high (of type 'class') part of name 'tosplit'
* Note: There may not be any need to support splitting to
* classes other than U4/I4 on RISC (assuming that registers are
* at least 32-bit).
*/
{
name *new;
signed_8 s8;
unsigned_8 u8;
signed_16 s16;
unsigned_16 u16;
unsigned_32 u32;
constant_defn *floatval;
switch( tosplit->n.class ) {
case N_CONSTANT:
if( tosplit->c.const_type == CONS_ABSOLUTE ) {
if( class == U1 ) {
u8 = ( tosplit->c.int_value >> 8 ) & 0xff;
new = AllocUIntConst( u8 );
} else if( class == I1 ) {
s8 = ( tosplit->c.int_value >> 8 ) & 0xff;
new = AllocIntConst( s8 );
} else if( class == U2 ) {
u16 = ( tosplit->c.int_value >> 16 ) & 0xffff;
new = AllocUIntConst( u16 );
} else if( class == I2 ) {
s16 = ( tosplit->c.int_value >> 16 ) & 0xffff;
new = AllocIntConst( s16 );
} else if( class == I4 ) {
new = AllocS32Const( tosplit->c.int_value_2 );
} else if( class == U4 ) {
new = AllocUIntConst( tosplit->c.int_value_2 );
} else if( class == FL ) {
_Zoiks( ZOIKS_129 );
} else { /* FD */
floatval = GetFloat( tosplit, FD );
u32 = (unsigned_32)floatval->value[ 3 ] << 16;
u32 += floatval->value[ 2 ];
new = AllocConst( CFCnvU32F( _TargetLongInt( u32 ) ) );
}
#if 0
} else if( tosplit->c.const_type == CONS_ADDRESS ) {
new = AddrConst( tosplit->c.value,
tosplit->c.int_value, CONS_SEGMENT );
#endif
} else {
_Zoiks( ZOIKS_044 );
}
break;
case N_REGISTER:
if( class == U1 || class == I1 ) {
new = AllocRegName( High16Reg( tosplit->r.reg ) );
} else if( class == U2 || class == I2 ) {
new = AllocRegName( High32Reg( tosplit->r.reg ) );
} else {
new = AllocRegName( High64Reg( tosplit->r.reg ) );
}
break;
case N_TEMP:
new = TempOffset( tosplit, tosplit->n.size/2, class );
if( new->t.temp_flags & CONST_TEMP ) {
name *cons = tosplit->v.symbol;
if( tosplit->n.name_class == FD ) {
cons = Int64Equivalent( cons );
}
new->v.symbol = HighPart( cons, class );
}
break;
case N_MEMORY:
new = AllocMemory( tosplit->v.symbol,
tosplit->v.offset + tosplit->n.size/2,
tosplit->m.memory_type, class );
new->v.usage = tosplit->v.usage;
break;
case N_INDEXED:
new = ScaleIndex( tosplit->i.index, tosplit->i.base,
tosplit->i.constant+ tosplit->n.size/2, class,
0, tosplit->i.scale, tosplit->i.index_flags );
break;
}
return( new );
}
extern name *OffsetMem( name *mem, type_length offset, type_class_def tipe ) {
/********************************************************************************/
name *new_mem;
if( mem->n.class == N_INDEXED ) {
new_mem = ScaleIndex( mem->i.index, mem->i.base,
mem->i.constant + offset, mem->n.name_class,
TypeClassSize[ tipe ], mem->i.scale, mem->i.index_flags );
} else {
assert( mem->n.class == N_TEMP );
new_mem = STempOffset( mem, offset, tipe, TypeClassSize[ tipe ] );
}
return( new_mem );
}
extern instruction *rSHR( instruction *ins ) {
/*************************************************/
type_class_def target_type;
name *temp_1;
name *temp_2;
instruction *first_ins;
instruction *new_ins;
// Since sizeof( reg ) > sizeof( int ), we could have junk
// hanging about in the high 32 bits (or whatever) of the
// operand. In order to conform to ANSI specs, we have to zero
// this out, or sign extend the operand if it's a signed
// shift right. To do this - we make a convert up to 8-byte
// thing and then convert back down afterwords.
target_type = U8;
if( Unsigned[ ins->type_class ] != ins->type_class ) {
target_type = I8;
}
temp_1 = AllocTemp( target_type );
temp_2 = AllocTemp( target_type );
first_ins = MakeConvert( ins->operands[ 0 ], temp_1, target_type, ins->type_class );
PrefixIns( ins, first_ins );
if( ins->operands[ 1 ]->n.class != N_CONSTANT ) {
new_ins = MakeConvert( ins->operands[ 1 ], temp_2, target_type, ins->type_class );
PrefixIns( ins, new_ins );
} else {
temp_2 = ins->operands[ 1 ];
}
new_ins = MakeBinary( OP_RSHIFT, temp_1, temp_2, temp_1, target_type );
PrefixIns( ins, new_ins );
new_ins = MakeConvert( temp_1, ins->result, ins->type_class, target_type );
ReplIns( ins, new_ins );
UpdateLive( first_ins, new_ins );
return( first_ins );
}
extern instruction *rMOVEXX_4( instruction *ins ) {
/******************************************************/
name *temp;
name *src;
name *dst;
type_length curr; // which quad word we are currently on
type_length size; // size of the structure
type_length words; // number of full quad-word writes to use
type_length rem; // number of bytes to write after last quad
instruction *new_ins;
instruction *first_ins;
instruction *last_ins;
/*
* Bust up a MOVXX into a series of 4-byte moves - we are guaranteed
* that both the source and dest are 4-byte aligned.
*/
assert( ins->operands[ 0 ]->n.class == N_TEMP || ins->operands[ 0 ]->n.class == N_INDEXED );
temp = AllocTemp( U4 );
size = ins->operands[ 0 ]->n.size;
first_ins = NULL;
last_ins = NULL;
curr = 0;
words = size / 4;
rem = size % 4;
if( rem ) {
if( ins->result->n.class == N_TEMP ) {
if( ( ins->result->t.temp_flags & ALIAS ) == EMPTY ) {
// we have a write to a struct on the stack which is a master
// since we don't 'pack' anything into the empty space after
// this struct, we can safely overwrite it and not bother
// doing the non-destructive last dword write
words += 1;
rem = 0;
}
}
}
while( words ) {
src = OffsetMem( ins->operands[ 0 ], curr, U4 );
dst = OffsetMem( ins->result, curr, U4 );
curr += 4;
words -= 1;
new_ins = MakeMove( src, temp, U4 );
PrefixIns( ins, new_ins );
if( first_ins == NULL ) {
first_ins = new_ins;
}
new_ins = MakeMove( temp, dst, U4 );
if( words == 0 && rem == 0 ) {
ReplIns( ins, new_ins );
last_ins = new_ins;
} else {
PrefixIns( ins, new_ins );
}
}
switch( rem ) {
case 0:
break;
case 1:
src = OffsetMem( ins->operands[ 0 ], curr, U1 );
dst = OffsetMem( ins->result, curr, U1 );
last_ins = MakeMove( src, temp, U1 );
if( first_ins == NULL ) {
first_ins = last_ins;
}
ReplIns( ins, last_ins );
break;
case 2:
src = OffsetMem( ins->operands[ 0 ], curr, U2 );
dst = OffsetMem( ins->result, curr, U2 );
last_ins = MakeMove( src, temp, U2 );
if( first_ins == NULL ) {
first_ins = last_ins;
}
ReplIns( ins, last_ins );
break;
case 3:
src = OffsetMem( ins->operands[ 0 ], curr, U1 );
dst = OffsetMem( ins->result, curr, U1 );
new_ins = MakeMove( src, temp, U1 );
PrefixIns( ins, new_ins );
if( first_ins == NULL ) {
first_ins = new_ins;
}
src = OffsetMem( ins->operands[ 0 ], curr, U2 );
dst = OffsetMem( ins->result, curr, U2 );
last_ins = MakeMove( src, temp, U2 );
ReplIns( ins, last_ins );
break;
default:
assert( 0 );
}
UpdateLive( first_ins, last_ins );
return( first_ins );
}
static void CnvOpToInt( instruction * ins, int op )
/***************************************************/
{
name *name1;
switch( ins->type_class ) {
#if 0
case FS:
name1 = ins->operands[op];
if( name1->n.class == N_CONSTANT ) {
ins->operands[op] = IntEquivalent( name1 );
}
break;
#endif
// this is for the I8 stuff - can't tell what to do in
// HighPart and LowPart if we don't get rid on constant
// here
case FD:
name1 = ins->operands[op];
if( name1->n.class == N_CONSTANT ) {
ins->operands[op] = Int64Equivalent( name1 );
}
break;
default:
break;
}
}
static bool IndexOverlaps( instruction *ins, int i )
/**************************************************/
{
if( ins->operands[ i ]->n.class != N_INDEXED ) return( FALSE );
if( SameThing( ins->operands[ i ]->i.index, ins->result ) ) return( TRUE );
return( FALSE );
}
/* Note: This could be used for 128-bit types implemented on top of
* 64-bit regs or anything along those lines.
*/
#define WORD U4
#define LONG_WORD U8
#define HIGH_WORD( x ) ( (x)->c.int_value_2 )
/* NB: The following routines are clones of their Intel counterparts
* with all segment related junk stripped off.
*/
extern instruction *rSPLITOP( instruction *ins )
/****************************************************
* Split a multi-word operation instruction.
*/
{
instruction *new_ins;
instruction *ins2;
name *temp;
if( IndexOverlaps( ins, 0 ) || IndexOverlaps( ins, 1 ) ) {
temp = AllocTemp( LONG_WORD );
HalfType( ins );
new_ins = MakeBinary( ins->head.opcode,
LowPart( ins->operands[0], WORD ),
LowPart( ins->operands[1], WORD ),
LowPart( temp, WORD ),
WORD );
ins2 = MakeBinary( ins->head.opcode,
HighPart( ins->operands[0], WORD ),
HighPart( ins->operands[1], WORD ),
HighPart( temp, WORD ),
WORD );
if( ins->head.opcode == OP_ADD ) {
ins2->head.opcode = OP_EXT_ADD;
} else if( ins->head.opcode == OP_SUB ) {
ins2->head.opcode = OP_EXT_SUB;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?