instruction *rFIXSHIFT( instruction *ins ) /*********************************************/ { instruction *new_ins; #ifndef NDEBUG signed_32 shift_count; #endif /* Fix up shift instructions that try to shift by too large amounts. This * can happen when optimizer merges adjacent shift instructions. Arithmetic * rights shifts must never exceed (REGISTER_BITS - 1), logical shifts can * be replaced with loads of zero constant. */ #ifndef NDEBUG assert( ins->operands[1]->n.class == N_CONSTANT ); shift_count = ins->operands[1]->c.lo.int_value; assert( shift_count >= REG_SIZE * 8 ); #endif if( ins->head.opcode == OP_RSHIFT && Signed[ins->type_class] == ins->type_class ) { ins->operands[1] = AllocS32Const( REG_SIZE * 8 - 1 ); return( ins ); } else { new_ins = MoveConst( 0, ins->result, ins->type_class ); DupSeg( ins, new_ins ); ReplIns( ins, new_ins ); return( new_ins ); } }
static instruction *KillCompare( instruction *ins, name *result ) { /******************************************************************/ instruction *new_ins; if( ins->result != NULL ) { new_ins = MakeMove( result, ins->result, ins->result->n.type_class ); DupSeg( ins, new_ins ); SetCSEBits( ins, new_ins ); ReplIns( ins, new_ins ); } else { new_ins = ins; DoNothing( ins ); } return( new_ins ); }
extern instruction *rSPLITMOVE( instruction *ins ) { /******************************************************/ instruction *new_ins; instruction *ins2; name *temp; CnvOpToInt( ins, 0 ); if( IndexOverlaps( ins, 0 ) ) { temp = AllocTemp( LONG_WORD ); new_ins = MakeMove( LowPart( ins->operands[ 0 ], WORD ), LowPart( temp, WORD ), WORD ); ins2 = MakeMove( HighPart( ins->operands[ 0 ], WORD ), HighPart( temp, WORD ), WORD ); DupSegOp( ins, new_ins, 0 ); DupSegOp( ins, ins2, 0 ); ins->operands[ 0 ] = temp; PrefixIns( ins, new_ins ); PrefixIns( ins, ins2 ); ins2 = MakeMove( LowPart( temp, WORD ), LowPart( ins->result, WORD ), WORD ); DupSegRes( ins, ins2 ); PrefixIns( ins, ins2 ); ins2 = MakeMove( HighPart( temp, WORD ), HighPart( ins->result, WORD ), WORD ); ReplIns( ins, ins2 ); } else { HalfType( ins ); new_ins = MakeMove( LowPart( ins->operands[ 0 ], ins->type_class ), LowPart( ins->result, ins->type_class ), ins->type_class ); DupSeg( ins, new_ins ); ins->operands[ 0 ] = HighPart( ins->operands[ 0 ], ins->type_class ); ins->result = HighPart( ins->result, ins->type_class ); if( new_ins->result->n.class == N_REGISTER && ins->operands[ 0 ]->n.class == N_REGISTER && HW_Ovlap( new_ins->result->r.reg, ins->operands[ 0 ]->r.reg ) ) { SuffixIns( ins, new_ins ); new_ins = ins; } else { PrefixIns( ins, new_ins ); } }
extern instruction *rSPLITOP( instruction *ins ) { /****************************************************/ 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; } ins2->table = CodeTable( ins2 ); new_ins->table = ins2->table; DupSegOp( ins, new_ins, 0 ); DupSegOp( ins, ins2, 0 ); DupSegOp( ins, new_ins, 1 ); DupSegOp( ins, ins2, 1 ); ins->operands[ 0 ] = temp; ins->operands[ 1 ] = temp; PrefixIns( ins, new_ins ); PrefixIns( ins, ins2 ); ins2 = MakeMove( LowPart( temp, WORD ), LowPart( ins->result, WORD ), WORD ); DupSegRes( ins, ins2 ); PrefixIns( ins, ins2 ); ins2 = MakeMove( HighPart( temp, WORD ), HighPart( ins->result, WORD ), WORD ); DupSegRes( ins, ins2 ); ReplIns( ins, ins2 ); } else { HalfType( ins ); new_ins = MakeBinary( ins->head.opcode, LowPart( ins->operands[ 0 ], ins->type_class ), LowPart( ins->operands[ 1 ], ins->type_class ), LowPart( ins->result, ins->type_class ), ins->type_class ); DupSeg( ins, new_ins ); ins->operands[ 0 ] = HighPart( ins->operands[ 0 ], ins->type_class ); ins->operands[ 1 ] = HighPart( ins->operands[ 1 ], ins->type_class ); ins->result = HighPart( ins->result, ins->type_class ); if( ins->head.opcode == OP_ADD ) { ins->head.opcode = OP_EXT_ADD; } else if( ins->head.opcode == OP_SUB ) { ins->head.opcode = OP_EXT_SUB; } /* Assign fake reduce table (from OP_EXT) to new_ins; default reduce table can generate INC and DEC which'll not set condition codes */ ins->table = CodeTable( ins ); new_ins->table = ins->table; PrefixIns( ins, new_ins ); } new_ins->ins_flags |= INS_CC_USED; return( new_ins ); }
instruction *rMAKECALL( instruction *ins ) /********************************************* Using the table RTInfo[], do all the necessary stuff to turn instruction "ins" into a call to a runtime support routine. Move the parms into registers, and move the return register of the runtime routine into the result. Used for 386 and 370 versions */ { rtn_info *info; label_handle lbl; instruction *left_ins; instruction *new_ins; instruction *last_ins; name *reg_name; hw_reg_set regs; hw_reg_set all_regs; hw_reg_set tmp; rt_class rtindex; if( !_IsConvert( ins ) ) { rtindex = LookupRoutine( ins ); } else { /* look it up again in case we ran out of memory during expansion*/ rtindex = LookupConvertRoutine( ins ); } info = &RTInfo[rtindex]; regs = _ParmReg( info->left ); all_regs = regs; left_ins = MakeMove( ins->operands[0], AllocRegName( regs ), info->operand_class ); ins->operands[0] = left_ins->result; MoveSegOp( ins, left_ins, 0 ); PrefixIns( ins, left_ins ); regs = _ParmReg( info->right ); if( !HW_CEqual( regs, HW_EMPTY ) ) { new_ins = MakeMove( ins->operands[1], AllocRegName( regs ), info->operand_class ); ins->operands[1] = new_ins->result; MoveSegOp( ins, new_ins, 0 ); HW_TurnOn( all_regs, regs ); PrefixIns( ins, new_ins ); } #if _TARGET & _TARG_370 tmp = RAReg(); HW_TurnOn( all_regs, tmp ); tmp = LNReg(); HW_TurnOn( all_regs, tmp ); #elif _TARGET & _TARG_80386 { tmp = ReturnReg( WD, false ); HW_TurnOn( all_regs, tmp ); } #endif reg_name = AllocRegName( all_regs ); lbl = RTLabel( rtindex ); new_ins = NewIns( 3 ); new_ins->head.opcode = OP_CALL; new_ins->type_class = ins->type_class; new_ins->operands[CALL_OP_USED] = reg_name; new_ins->operands[CALL_OP_USED2] = reg_name; new_ins->operands[CALL_OP_ADDR] = AllocMemory( lbl, 0, CG_LBL, ins->type_class ); new_ins->result = NULL; new_ins->num_operands = 2; /* special case for OP_CALL*/ #if _TARGET & _TARG_AXP { HW_CTurnOn( all_regs, HW_FULL ); HW_TurnOff( all_regs, SavedRegs() ); HW_CTurnOff( all_regs, HW_UNUSED ); HW_TurnOn( all_regs, ReturnAddrReg() ); } #endif new_ins->zap = (register_name *)AllocRegName( all_regs ); /* all parm regs could be zapped*/ last_ins = new_ins; if( ins->result == NULL || _OpIsCondition( ins->head.opcode ) ) { /* comparison, still need conditional jumps*/ ins->operands[0] = AllocIntConst( 0 ); ins->operands[1] = AllocIntConst( 1 ); DelSeg( ins ); DoNothing( ins ); /* just conditional jumps for ins*/ PrefixIns( ins, new_ins ); new_ins->ins_flags |= INS_CC_USED; last_ins = ins; } else { regs = _ParmReg( info->result ); tmp = regs; HW_TurnOn( tmp, new_ins->zap->reg ); new_ins->zap = (register_name *)AllocRegName( tmp ); reg_name = AllocRegName( regs ); new_ins->result = reg_name; last_ins = MakeMove( reg_name, ins->result, ins->type_class ); ins->result = last_ins->operands[0]; MoveSegRes( ins, last_ins ); SuffixIns( ins, last_ins ); ReplIns( ins, new_ins ); } FixCallIns( new_ins ); UpdateLive( left_ins, last_ins ); return( left_ins ); }
static instruction *FoldAbsolute( instruction *ins ) { /********************************************************* See below. */ instruction *new_ins; opcnt num_operands; name *result; tn fold; type_def *tipe; type_def *left_tipe; type_def *rite_tipe; type_def *fold_tipe; pointer left; pointer rite; name *tmp; name *new_const; float_handle value; tipe = ClassType( ins->type_class ); left_tipe = ClassType( _OpClass( ins ) ); num_operands = OpcodeNumOperands( ins ); left = NULL; rite = NULL; if( num_operands != 0 ) { left = TName( ins->operands[0], left_tipe ); if( num_operands > 1 ) { if( ins->operands[1]->n.type_class == XX ) { rite_tipe = tipe; } else { rite_tipe = ClassType( ins->operands[1]->n.type_class ); } rite = TName( ins->operands[1], rite_tipe ); } } fold = NULL; switch( ins->head.opcode ) { case OP_ADD: fold = FoldPlus( left, rite, tipe ); break; case OP_SUB: fold = FoldMinus( left, rite, tipe ); break; case OP_MUL: fold = FoldTimes( left, rite, tipe ); break; case OP_DIV: fold = FoldDiv( left, rite, tipe ); break; case OP_MOD: fold = FoldMod( left, rite, tipe ); break; case OP_AND: fold = FoldAnd( left, rite, tipe ); break; case OP_OR: fold = FoldOr( left, rite, tipe ); break; case OP_XOR: fold = FoldXor( left, rite, tipe ); break; case OP_RSHIFT: fold = FoldRShift( left, rite, tipe ); break; case OP_LSHIFT: fold = FoldLShift( left, rite, tipe ); break; case OP_NEGATE: fold = FoldUMinus( left, tipe ); break; case OP_COMPLEMENT: fold = Fold1sComp( left, tipe ); break; case OP_CONVERT: // look out for CNV PT U2 t1 type instructions; if sizeof( PT ) is greater // than sizeof( U2 ), we don't want to fold or we'll screw up based pointers if( IsTrickyPointerConv( ins ) ) return( NULL ); // fall through! case OP_ROUND: fold = FoldCnvRnd( (cg_op)ins->head.opcode, left, tipe ); break; case OP_CMP_EQUAL: case OP_CMP_NOT_EQUAL: case OP_CMP_GREATER: case OP_CMP_LESS_EQUAL: case OP_CMP_LESS: case OP_CMP_GREATER_EQUAL: if( ActiveCompare( ins ) ) { fold = FoldCompare( (cg_op)ins->head.opcode, left, rite, tipe ); if( fold != NULL ) { return( StraightLine( ins, fold, true ) ); } } break; case OP_BIT_TEST_TRUE: if( ActiveCompare( ins ) ) { fold = FoldAnd( left, rite, tipe ); if( fold != NULL ) { return( StraightLine( ins, fold, true ) ); } } break; case OP_BIT_TEST_FALSE: if( ActiveCompare( ins ) ) { fold = FoldAnd( left, rite, tipe ); if( fold != NULL ) { return( StraightLine( ins, fold, false ) ); } } break; default: fold = NULL; break; } if( fold != NULL ) { fold_tipe = fold->tipe; result = TGetName( fold ); if( result != NULL && !NeedConvert( fold_tipe, tipe ) ) { ins->table = NULL; // look out for scary DIV U4 EDX:EAX, c1 -> t1 type instructions if( result->n.class != N_CONSTANT && result->n.size != TypeClassSize[ins->type_class] ) return( NULL ); // look out for scary MUL U4 EDX:EAX, c1 -> t1 type instructions if( result->n.class != N_CONSTANT && ins->result->n.size != TypeClassSize[ins->type_class] ) return( NULL ); new_ins = MakeMove( result, ins->result, ins->type_class ); SetCSEBits( ins, new_ins ); DupSeg( ins, new_ins ); ReplIns( ins, new_ins ); return( new_ins ); }