mipssplit.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 427 行 · 第 1/2 页
C
427 行
/**********************************************/
{
instruction *first_ins;
instruction *new_ins;
name *mem_1;
name *mem_2;
name *temp;
mem_1 = OffsetMem( ins->operands[0], 3, U4 );
mem_2 = OffsetMem( ins->operands[0], 0, U4 );
temp = AllocTemp( U4 );
first_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_1, temp, U4 );
PrefixIns( ins, first_ins );
new_ins = MakeUnary( OP_LOAD_UNALIGNED, mem_2, temp, U4 );
PrefixIns( ins, new_ins );
new_ins = MakeMove( temp, ins->result, U4 );
ReplIns( ins, new_ins );
UpdateLive( first_ins, new_ins );
return( first_ins );
}
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() );
// TODO: these regs are most likely wrong for MIPS
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 );
}
/* MIPS is a little weird - it only has 'set' instruction for
* 'less than' (reg/reg and reg/imm variants). Conditional branch
* instructions can't take an immediate operand (except $zero of course)
* and there isn't a full set of reg/reg conditional branches. So we
* have to carefully reduce the instructions here...
* NB: This is a clone of rSIMPCMP from rscsplit.c
*/
extern instruction *rM_SIMPCMP( instruction *ins )
/******************************************************/
{
instruction *new;
opcode_defs opcode;
bool reverse;
reverse = FALSE;
assert( ins->result == NULL );
switch( ins->head.opcode ) {
case OP_CMP_NOT_EQUAL:
reverse = TRUE;
/* fall through */
case OP_CMP_EQUAL:
opcode = OP_SET_EQUAL;
break;
case OP_CMP_GREATER:
reverse = TRUE;
/* fall through */
case OP_CMP_LESS_EQUAL:
opcode = OP_SET_LESS_EQUAL;
/* Special reduction: use OP_SET_LESS but increment constant */
if( (ins->operands[1]->n.class == N_CONSTANT)
&& (ins->operands[1]->c.const_type == CONS_ABSOLUTE) ) {
signed_32 value;
opcode = OP_SET_LESS;
// TODO: we may be leaking memory here by losing track of the
// original constant operand
value = ins->operands[1]->c.int_value;
ins->operands[1] = AllocS32Const( value + 1 );
}
if( ins->operands[1]->n.class == N_REGISTER ) {
// Swap operands and reverse condition - we can do slt/sltu but
// nothing else
return( rSWAPCMP( ins ) );
}
break;
case OP_CMP_GREATER_EQUAL:
reverse = TRUE;
/* fall through */
case OP_CMP_LESS:
opcode = OP_SET_LESS;
break;
}
ins->result = AllocTemp( ins->type_class );
switch( ins->type_class ) {
case I4:
case U4:
ins->table = OpcodeTable( BIN4 );
break;
case I8:
case U8:
ins->table = OpcodeTable( BIN8 );
break;
case FS:
ins->table = OpcodeTable( FBINS );
break;
case FD:
case FL:
ins->table = OpcodeTable( FBIND );
break;
default:
_Zoiks( ZOIKS_096 );
}
ins->head.opcode = opcode;
opcode = OP_CMP_NOT_EQUAL;
if( reverse ) {
opcode = OP_CMP_EQUAL;
}
new = MakeCondition( opcode, ins->result, AllocS32Const( 0 ), _TrueIndex( ins ), _FalseIndex( ins ), ins->type_class );
SuffixIns( ins, new );
return( new );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?