axpsplit.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 703 行 · 第 1/2 页
C
703 行
extern instruction *rSTORE_4U( instruction *ins ) {
/******************************************************/
instruction *first_ins;
instruction *new_ins;
name *high;
name *low;
name *temp_high;
name *temp_low;
name *addr;
name *mem_high;
name *mem_low;
name *value;
mem_low = OffsetMem( ins->result, 0, U8 );
mem_high = OffsetMem( ins->result, 3, U8 );
value = AllocTemp( U8 );
addr = AllocTemp( U8 );
high = AllocTemp( U8 );
low = AllocTemp( U8 );
temp_high = AllocTemp( U8 );
temp_low = AllocTemp( U8 );
first_ins = MakeConvert( ins->operands[ 0 ], value, U8, ins->type_class );
PrefixIns( ins, first_ins );
new_ins = MakeUnary( OP_LA, mem_low, addr, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_high, high, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_low, low, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeNary( OP_INSERT_HIGH, value, addr, temp_high, U8, U4, 2 );
PrefixIns( ins, new_ins );
new_ins = MakeNary( OP_INSERT_LOW, value, addr, temp_low, U8, U4, 2 );
PrefixIns( ins, new_ins );
new_ins = MakeNary( OP_MASK_HIGH, high, addr, high, U8, U4, 2 );
PrefixIns( ins, new_ins );
new_ins = MakeNary( OP_MASK_LOW, low, addr, low, U8, U4, 2 );
PrefixIns( ins, new_ins );
new_ins = MakeBinary( OP_OR, high, temp_high, high, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeBinary( OP_OR, low, temp_low, low, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeUnary( OP_STORE_UNALIGNED, high, mem_high, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeUnary( OP_STORE_UNALIGNED, low, mem_low, U8 );
ReplIns( ins, new_ins );
UpdateLive( first_ins, new_ins );
return( first_ins );
}
extern instruction *rLOAD_8U( instruction *ins ) {
/*****************************************************/
_Zoiks( ZOIKS_091 );
return( ins );
}
extern instruction *rSTORE_8U( instruction *ins ) {
/******************************************************/
_Zoiks( ZOIKS_091 );
return( ins );
}
extern instruction *rMOVEXX_8( instruction *ins ) {
/******************************************************/
name *bit_mask;
name *temp;
name *temp_2;
name *src;
name *dst;
type_length curr; // which quad word we are currently on
type_length size; // size of the structure
type_length quads; // 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 8-byte moves - we are guaranteed
* that both the source and dest are 8-byte aligned.
*/
assert( ins->operands[ 0 ]->n.class == N_TEMP || ins->operands[ 0 ]->n.class == N_INDEXED );
temp = AllocTemp( U8 );
size = ins->operands[ 0 ]->n.size;
first_ins = NULL;
last_ins = NULL;
curr = 0;
quads = size / 8;
rem = size % 8;
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 quad-word write
quads += 1;
rem = 0;
}
}
}
while( quads ) {
src = OffsetMem( ins->operands[ 0 ], curr, U8 );
dst = OffsetMem( ins->result, curr, U8 );
curr += 8;
quads -= 1;
new_ins = MakeMove( src, temp, U8 );
PrefixIns( ins, new_ins );
if( first_ins == NULL ) {
first_ins = new_ins;
}
new_ins = MakeMove( temp, dst, U8 );
if( quads == 0 && rem == 0 ) {
ReplIns( ins, new_ins );
last_ins = new_ins;
} else {
PrefixIns( ins, new_ins );
}
}
if( rem != 0 ) {
if( rem == 4 ) {
src = OffsetMem( ins->operands[ 0 ], curr, U4 );
dst = OffsetMem( ins->result, curr, U4 );
temp_2 = AllocTemp( U4 );
new_ins = MakeMove( src, temp_2, U4 );
PrefixIns( ins, new_ins );
if( first_ins == NULL ) {
first_ins = new_ins;
}
new_ins = MakeMove( temp_2, dst, U4 );
ReplIns( ins, new_ins );
last_ins = new_ins;
} else {
src = OffsetMem( ins->operands[ 0 ], curr, U8 );
dst = OffsetMem( ins->result, curr, U8 );
temp_2 = AllocTemp( U8 );
bit_mask = AllocS32Const( ( 1 << rem ) - 1 );
new_ins = MakeMove( src, temp, U8 );
PrefixIns( ins, new_ins );
if( first_ins == NULL ) {
first_ins = new_ins;
}
new_ins = MakeMove( dst, temp_2, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeBinary( OP_ZAP_NOT, temp, bit_mask, temp, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeBinary( OP_ZAP, temp_2, bit_mask, temp_2, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeBinary( OP_OR, temp_2, temp, temp, U8 );
PrefixIns( ins, new_ins );
new_ins = MakeMove( temp, dst, U8 );
ReplIns( ins, new_ins );
last_ins = new_ins;
}
}
UpdateLive( first_ins, last_ins );
return( first_ins );
}
#if 0
extern instruction *rCONSTLOAD( instruction *ins ) {
/*******************************************************/
signed_16 high;
signed_16 low;
signed_16 extra;
assert( ins->operands[ 0 ]->n.class == N_CONSTANT );
assert( ins->operands[ 0 ]->c.const_type == CONS_ABSOLUTE );
first = NULL;
FactorInt32( ins->operands[ 0 ]->c.int_value, &high, &extra, &low );
// work to be done here - need some way of accurately representing
// the ldah rn,extra(rn) instruction
}
#else
extern instruction *rCONSTLOAD( instruction *ins ) {
/*******************************************************/
instruction *new_ins;
instruction *first_ins;
name *high_part;
name *low_part;
name *temp;
name *cons;
unsigned_32 high;
unsigned_32 low;
unsigned_32 k;
unsigned_32 c;
type_class_def index_class;
bool cruft_in_high_dword;
assert( ins->operands[ 0 ]->n.class == N_CONSTANT );
assert( ins->operands[ 0 ]->c.const_type == CONS_ABSOLUTE );
cons = ins->operands[ 0 ];
c = cons->c.int_value;
k = 65536U;
high = c / k;
low = c % k;
if( low >= ( k / 2 ) ) {
high += 1;
low -= k;
}
assert( ( (signed_16)high * k + (signed_16)low ) == c );
high_part = AllocAddrConst( NULL, high, CONS_HIGH_ADDR, ins->type_class );
if( low == 0 ) {
first_ins = MakeMove( high_part, ins->result, ins->type_class );
ReplIns( ins, first_ins );
if( ( c & 0x80000000 ) &&
( first_ins->type_class == Unsigned[ first_ins->type_class ] ) ) {
new_ins = MakeBinary( OP_ZAP_NOT, first_ins->result, AllocS32Const( 0x0f ), first_ins->result, first_ins->type_class );
SuffixIns( first_ins, new_ins );
UpdateLive( first_ins, new_ins );
}
} else {
index_class = I4;
temp = AllocTemp( index_class );
first_ins = MakeMove( high_part, temp, index_class );
PrefixIns( ins, first_ins );
low_part = AllocIndex( temp, NULL, low, ins->type_class );
new_ins = MakeUnary( OP_LA, low_part, ins->result, ins->type_class );
PrefixIns( ins, new_ins );
cruft_in_high_dword = FALSE;
if( c >= 0x7fff8000 && c <= 0x7fffffff ) {
cruft_in_high_dword = TRUE;
}
if( ( c & 0x80000000 ) &&
( ins->type_class == Unsigned[ ins->type_class ] ) ) {
cruft_in_high_dword = TRUE;
}
if( cruft_in_high_dword ) {
new_ins = MakeBinary( OP_ZAP_NOT, ins->result, AllocS32Const( 0x0f ), ins->result, ins->type_class );
PrefixIns( ins, new_ins );
}
FreeIns( ins );
UpdateLive( first_ins, new_ins );
}
return( first_ins );
}
#endif
static instruction *CheapCall( instruction *ins, int rt_call, name *p1, name *p2 ) {
/**********************************************************************************/
instruction *call;
hw_reg_set reg;
name *reg_name;
label_handle lbl;
reg = HW_EMPTY;
lbl = RTLabel( rt_call );
call = NewIns( 3 );
call->head.opcode = OP_CALL;
call->type_class = WD;
call->operands[ CALL_OP_USED ] = p1;
call->operands[ CALL_OP_USED2 ] = p2;
call->operands[ CALL_OP_ADDR ]= AllocMemory( lbl, 0, CG_LBL, WD );
call->result = NULL;
call->num_operands = 2; /* special case for OP_CALL*/
HW_TurnOn( reg, ReturnAddrReg() );
HW_TurnOn( reg, ScratchReg() );
HW_CTurnOn( reg, HW_R1 ); // know this is only other reg modified!
HW_CTurnOn( reg, HW_R2 ); // and this one two!
HW_CTurnOn( reg, HW_R3 ); // and this one three!
reg_name = AllocRegName( reg );
call->zap = ®_name->r;
PrefixIns( ins, call );
return( call );
}
static void CopyStack( instruction *ins, name *alloc_size, type_length arg_size ) {
/*********************************************************************************/
instruction *new_ins;
name *p1;
name *p2;
p1 = AllocRegName( HW_D1 );
new_ins = MakeMove( alloc_size, p1, WD );
PrefixIns( ins, new_ins );
p2 = AllocRegName( HW_D2 );
new_ins = MakeMove( AllocS32Const( arg_size ), p2, WD );
PrefixIns( ins, new_ins );
CheapCall( ins, RT_STK_COPY, p1, p2 );
}
extern instruction *rALLOCA( instruction *ins ) {
/***********************************************/
name *sreg;
name *amount;
name *real_amount;
name *temp;
unsigned_32 value;
instruction *first;
instruction *last;
type_class_def class;
unsigned_32 stack_align;
bool check;
sreg = AllocRegName( StackReg() );
amount = ins->operands[ 0 ];
temp = AllocTemp( ins->type_class );
class = WD;
stack_align = STACK_ALIGNMENT;
check = TRUE;
CurrProc->targ.base_is_fp = TRUE;
if( amount->n.class == N_CONSTANT && amount->c.const_type == CONS_ABSOLUTE ) {
value = amount->c.int_value;
value = _RoundUp( value, stack_align );
real_amount = AllocS32Const( value );
first = MakeBinary( OP_SUB, sreg, AllocS32Const( value ), temp, class );
PrefixIns( ins, first );
if( value <= ( PAGE_SIZE - 7 ) ) {
check = FALSE;
}
} else {
real_amount = AllocTemp( ins->type_class );
first = MakeBinary( OP_ADD, amount, AllocS32Const( stack_align - 1 ), temp, class );
PrefixIns( ins, first );
last = MakeBinary( OP_AND, temp, AllocS32Const( ~( stack_align - 1 ) ), real_amount, class );
PrefixIns( ins, last );
last = MakeBinary( OP_SUB, sreg, real_amount, temp, class );
PrefixIns( ins, last );
}
last = MakeMove( temp, sreg, WD );
PrefixIns( ins, last );
if( check ) {
CheapCall( ins, RT_STK_CRAWL, AllocRegName( HW_EMPTY ), AllocRegName( HW_EMPTY ) );
}
if( MaxStack != 0 ) {
if( _IsModel( MICROSOFT_COMPATIBLE ) ) {
// in order to support doing alloca's in parm lists, we copy
// the parm cache area down now
CopyStack( ins, real_amount, MaxStack );
}
last = MakeBinary( OP_ADD, temp, AllocS32Const( MaxStack ), ins->result, class );
} else {
last = MakeMove( temp, ins->result, class );
}
ReplIns( ins, last );
UpdateLive( first, last );
return( first );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?