static void FlowConditions( void ) /************************************* For each block in the program, first "GatherSources" to determine what the state of the condition codes are on entry to the routine, then "Traverse" the block, to see if there is an instruction that sets the condition codes for the conditional branches at the end of the block correctly, or if the condition codes from previous blocks are unaffected by the block and will suffice for the final branch. */ { block *blk; name *zero; bool change; zero = AllocIntConst( 0 ); change = true; for( ;; ) { for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) { GatherSources( blk ); change |= Traverse( blk, zero ); } if( change == false ) break; change = false; } }
static an FlowOut( an node, type_def *tipe ) { /**************************************************/ name *temp; label_handle lbl; lbl = AskForNewLabel(); temp = BGGlobalTemp( tipe ); AddIns( MakeMove( AllocIntConst( FETrue() ), temp, temp->n.type_class ) ); *(node->u.b.t) = CurrBlock->label; GenBlock( BLK_JUMP, 1 ); AddTarget( lbl, false ); EnLink( AskForNewLabel(), true ); AddIns( MakeMove( AllocIntConst( 0 ), temp, temp->n.type_class ) ); *(node->u.b.f) = CurrBlock->label; GenBlock( BLK_JUMP, 1 ); AddTarget( lbl, false ); EnLink( lbl, true ); NamesCrossBlocks(); AddrFree( node ); return( AddrName( temp, tipe ) ); }
static instruction *CmpRelocZero( instruction *ins, opcnt c, opcnt r ) /*********************************************************************/ { name *cons; name *rel; bool truth; if( OpcodeNumOperands( ins ) != 2 ) return( NULL ); cons = ins->operands[c]; if( cons->n.class != N_CONSTANT ) return( NULL ); if( cons->c.const_type != CONS_ABSOLUTE ) return( NULL ); if( CFTest( cons->c.value ) != 0 ) return( NULL ); rel = ins->operands[r]; if( rel->c.const_type == CONS_OFFSET && !AskSegIsNear( (segment_id)rel->c.lo.int_value ) ) return( NULL ); switch( ins->head.opcode ) { case OP_BIT_TEST_FALSE: case OP_CMP_EQUAL: case OP_CMP_LESS: case OP_CMP_LESS_EQUAL: truth = false; break; case OP_BIT_TEST_TRUE: case OP_CMP_GREATER: case OP_CMP_GREATER_EQUAL: case OP_CMP_NOT_EQUAL: truth = true; break; default: return( false ); } if( !ActiveCompare( ins ) ) return( NULL ); if( c != 1 ) truth = !truth; if( truth ) { _SetBlockIndex( ins, _TrueIndex(ins), _TrueIndex(ins) ); } else { _SetBlockIndex( ins, _FalseIndex(ins), _FalseIndex(ins) ); } return( KillCompare( ins, AllocIntConst( truth ? FETrue() : 0 ) ) ); }
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 ); }