<s> static void alpha_setup_incoming_varargs ( cumulative_args_t pcum , const function_arg_info & arg , int * pretend_size , int no_rtl ) { CUMULATIVE_ARGS cum = * get_cumulative_args ( pcum ) ; if ( ! TYPE_NO_NAMED_ARGS_STDARG_P ( TREE_TYPE ( current_function_decl ) ) ) targetm . calls . function_arg_advance ( pack_cumulative_args ( & cum ) , arg ) ; if ( cum . num_args < 6 ) { if ( ! no_rtl ) { emit_move_insn ( gen_rtx_REG ( DImode , 1 ) , virtual_incoming_args_rtx ) ; emit_insn ( gen_arg_home ( ) ) ; } * pretend_size = 7 * UNITS_PER_WORD ; } if ( cum >= 6 ) return ; if ( ! no_rtl ) { int count ; alias_set_type set = get_varargs_alias_set ( ) ; rtx tmp ; count = cfun -> va_list_gpr_size / UNITS_PER_WORD ; if ( count > 6 - cum ) count = 6 - cum ; gcc_assert ( ( VA_LIST_MAX_FPR_SIZE & 3 ) == 3 ) ; if ( cfun -> va_list_fpr_size & 1 ) { tmp = gen_rtx_MEM ( BLKmode , plus_constant ( Pmode , virtual_incoming_args_rtx , ( cum + 6 ) * UNITS_PER_WORD ) ) ; MEM_NOTRAP_P ( tmp ) = 1 ; set_mem_alias_set ( tmp , set ) ; move_block_from_reg ( 16 + cum , tmp , count ) ; } if ( cfun -> va_list_fpr_size & 2 ) { tmp = gen_rtx_MEM ( BLKmode , plus_constant ( Pmode , virtual_incoming_args_rtx , cum * UNITS_PER_WORD ) ) ; MEM_NOTRAP_P ( tmp ) = 1 ; set_mem_alias_set ( tmp , set ) ; move_block_from_reg ( 16 + cum + TARGET_FPREGS * 32 , tmp , count ) ; } } * pretend_size = 12 * UNITS_PER_WORD ; } </s>

Perform any needed actions needed for a function that is receiving a variable number of arguments .


<s> int alpha_store_data_bypass_p ( rtx_insn * out_insn , rtx_insn * in_insn ) { rtx in_set = single_set ( in_insn ) ; if ( in_set ) return alpha_store_data_bypass_p_1 ( out_insn , in_set ) ; rtx in_pat = PATTERN ( in_insn ) ; if ( GET_CODE ( in_pat ) != PARALLEL ) return false ; for ( int i = 0 ; i < XVECLEN ( in_pat , 0 ) ; i ++ ) { rtx in_exp = XVECEXP ( in_pat , 0 , i ) ; if ( GET_CODE ( in_exp ) == CLOBBER || GET_CODE ( in_exp ) == USE || GET_CODE ( in_exp ) == TRAP_IF ) continue ; gcc_assert ( GET_CODE ( in_exp ) == SET ) ; if ( ! alpha_store_data_bypass_p_1 ( out_insn , in_exp ) ) return false ; } return true ; } </s>

True if the dependency between OUT_INSN and IN_INSN is on the store data not the address operand ( s ) of the store . IN_INSN and OUT_INSN must be either a single_set or a PARALLEL with SETs inside . This alpha-specific version of store_data_bypass_p ignores TRAP_IF that would result in assertion failure ( and internal compiler error ) in the generic store_data_bypass_p function .


<s> static bool alpha_store_data_bypass_p_1 ( rtx_insn * out_insn , rtx in_set ) { if ( ! MEM_P ( SET_DEST ( in_set ) ) ) return false ; rtx out_set = single_set ( out_insn ) ; if ( out_set ) return ! reg_mentioned_p ( SET_DEST ( out_set ) , SET_DEST ( in_set ) ) ; rtx out_pat = PATTERN ( out_insn ) ; if ( GET_CODE ( out_pat ) != PARALLEL ) return false ; for ( int i = 0 ; i < XVECLEN ( out_pat , 0 ) ; i ++ ) { rtx out_exp = XVECEXP ( out_pat , 0 , i ) ; if ( GET_CODE ( out_exp ) == CLOBBER || GET_CODE ( out_exp ) == USE || GET_CODE ( out_exp ) == TRAP_IF ) continue ; gcc_assert ( GET_CODE ( out_exp ) == SET ) ; if ( reg_mentioned_p ( SET_DEST ( out_exp ) , SET_DEST ( in_set ) ) ) return false ; } return true ; } </s>

Helper function for alpha_store_data_bypass_p , handle just a single SET IN_SET .


<s> rtx alpha_gp_save_rtx ( ) { rtx r = get_hard_reg_initial_val ( DImode , 29 ) ; if ( GET_CODE ( r ) != MEM ) r = gen_mem_addressof ( r , NULL_TREE ) ; return r ; } </s>

Return or create a pseudo containing the gp value for the current function . Needed only if TARGET_LD_BUGGY_LDGP .


<s> static int alpha_issue_rate ( ) { return ( alpha_cpu == PROCESSOR_EV4 ? 2 : 4 ) ; } </s>

Function to initialize the issue rate used by the scheduler .


<s> int direct_return ( ) { return ( ! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK && reload_completed && alpha_sa_size ( ) == 0 && get_frame_size ( ) == 0 && current_function_outgoing_args_size == 0 && current_function_pretend_args_size == 0 ) ; } </s>

Return non-zero if this function is known to have a null epilogue .


<s> static const char * get_round_mode_suffix ( ) { enum attr_round_suffix s = get_attr_round_suffix ( current_output_insn ) ; switch ( s ) { case ROUND_SUFFIX_NONE : return NULL ; case ROUND_SUFFIX_NORMAL : switch ( alpha_fprm ) { case ALPHA_FPRM_NORM : return NULL ; case ALPHA_FPRM_MINF : return "m" ; case ALPHA_FPRM_CHOP : return "c" ; case ALPHA_FPRM_DYN : return "d" ; } break ; case ROUND_SUFFIX_C : return "c" ; } abort ( ) ; } </s>

Return the rounding mode suffix applicable to the current instruction , or NULL .


<s> static const char * get_trap_mode_suffix ( ) { enum attr_trap_suffix s = get_attr_trap_suffix ( current_output_insn ) ; switch ( s ) { case TRAP_SUFFIX_NONE : return NULL ; case TRAP_SUFFIX_SU : if ( alpha_fptm >= ALPHA_FPTM_SU ) return "su" ; return NULL ; case TRAP_SUFFIX_SUI : if ( alpha_fptm >= ALPHA_FPTM_SUI ) return "sui" ; return NULL ; case TRAP_SUFFIX_V_SV : switch ( alpha_fptm ) { case ALPHA_FPTM_N : return NULL ; case ALPHA_FPTM_U : return "v" ; case ALPHA_FPTM_SU : case ALPHA_FPTM_SUI : return "sv" ; } break ; case TRAP_SUFFIX_V_SV_SVI : switch ( alpha_fptm ) { case ALPHA_FPTM_N : return NULL ; case ALPHA_FPTM_U : return "v" ; case ALPHA_FPTM_SU : return "sv" ; case ALPHA_FPTM_SUI : return "svi" ; } break ; case TRAP_SUFFIX_U_SU_SUI : switch ( alpha_fptm ) { case ALPHA_FPTM_N : return NULL ; case ALPHA_FPTM_U : return "u" ; case ALPHA_FPTM_SU : return "su" ; case ALPHA_FPTM_SUI : return "sui" ; } break ; } abort ( ) ; } </s>

Return the trap mode suffix applicable to the current instruction , or NULL .

alpha "su" "sui" "v" "sv" "v" "sv" "svi" "u" "su" "sui"


<s> static rtx set_frame_related_p ( ) { rtx seq = gen_sequence ( ) ; end_sequence ( ) ; if ( GET_CODE ( seq ) == SEQUENCE ) { int i = XVECLEN ( seq , 0 ) ; while ( -- i >= 0 ) RTX_FRAME_RELATED_P ( XVECEXP ( seq , 0 , i ) ) = 1 ; return emit_insn ( seq ) ; } else { seq = emit_insn ( seq ) ; RTX_FRAME_RELATED_P ( seq ) = 1 ; return seq ; } } </s>

Helper function to set RTX_FRAME_RELATED_P on instructions , including sequences .


<s> static const char * unicosmk_ssib_name ( ) { static char name [ 256 ] ; rtx x ; const char * fnname ; int len ; x = DECL_RTL ( cfun -> decl ) ; if ( GET_CODE ( x ) != MEM ) abort ( ) ; x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) != SYMBOL_REF ) abort ( ) ; fnname = XSTR ( x , 0 ) ; STRIP_NAME_ENCODING ( fnname , fnname ) ; len = strlen ( fnname ) ; if ( len + SSIB_PREFIX_LEN > 255 ) len = 255 - SSIB_PREFIX_LEN ; strcpy ( name , SSIB_PREFIX ) ; strncpy ( name + SSIB_PREFIX_LEN , fnname , len ) ; name [ len + SSIB_PREFIX_LEN ] = 0 ; return name ; } </s>

Generate the name of the SSIB section for the current function .


<s> static rtx alphaev4_next_group ( rtx insn , int * pin_use , int * plen ) { int len , in_use ; len = in_use = 0 ; if ( ! INSN_P ( insn ) || GET_CODE ( PATTERN ( insn ) ) == CLOBBER || GET_CODE ( PATTERN ( insn ) ) == USE ) goto next_and_done ; while ( 1 ) { enum alphaev4_pipe pipe ; pipe = alphaev4_insn_pipe ( insn ) ; switch ( pipe ) { case EV4_STOP : if ( in_use ) goto done ; if ( recog_memoized ( insn ) < 0 ) len = - 1 ; else len = get_attr_length ( insn ) ; goto next_and_done ; case EV4_IBX : if ( in_use & EV4_IB0 ) { if ( in_use & EV4_IB1 ) goto done ; in_use |= EV4_IB1 ; } else in_use |= EV4_IB0 | EV4_IBX ; break ; case EV4_IB0 : if ( in_use & EV4_IB0 ) { if ( ! ( in_use & EV4_IBX ) || ( in_use & EV4_IB1 ) ) goto done ; in_use |= EV4_IB1 ; } in_use |= EV4_IB0 ; break ; case EV4_IB1 : if ( in_use & EV4_IB1 ) goto done ; in_use |= EV4_IB1 ; break ; default : gcc_unreachable ( ) ; } len += 4 ; if ( GET_CODE ( insn ) == JUMP_INSN ) goto next_and_done ; next : insn = next_nonnote_insn ( insn ) ; if ( ! insn || ! INSN_P ( insn ) ) goto done ; if ( GET_MODE ( insn ) == TImode ) goto done ; if ( GET_CODE ( insn ) == CLOBBER || GET_CODE ( insn ) == USE ) goto next ; } next_and_done : insn = next_nonnote_insn ( insn ) ; done : * plen = len ; * pin_use = in_use ; return insn ; } </s>

IN_USE is a mask of the slots currently filled within the insn group . The mask bits come from alphaev4_pipe above . If EV4_IBX is set , then the insn in EV4_IB0 can be swapped by the hardware into EV4_IB1 . LEN is , of course , the length of the group in bytes .


<s> static rtx alphaev5_next_group ( rtx insn , int * pin_use , int * plen ) { int len , in_use ; len = in_use = 0 ; if ( ! INSN_P ( insn ) || GET_CODE ( PATTERN ( insn ) ) == CLOBBER || GET_CODE ( PATTERN ( insn ) ) == USE ) goto next_and_done ; while ( 1 ) { enum alphaev5_pipe pipe ; pipe = alphaev5_insn_pipe ( insn ) ; switch ( pipe ) { case EV5_STOP : if ( in_use ) goto done ; if ( recog_memoized ( insn ) < 0 ) len = - 1 ; else len = get_attr_length ( insn ) ; goto next_and_done ; case EV5_E01 : if ( in_use & EV5_E0 ) { if ( in_use & EV5_E1 ) goto done ; in_use |= EV5_E1 ; } else in_use |= EV5_E0 | EV5_E01 ; break ; case EV5_E0 : if ( in_use & EV5_E0 ) { if ( ! ( in_use & EV5_E01 ) || ( in_use & EV5_E1 ) ) goto done ; in_use |= EV5_E1 ; } in_use |= EV5_E0 ; break ; case EV5_E1 : if ( in_use & EV5_E1 ) goto done ; in_use |= EV5_E1 ; break ; case EV5_FAM : if ( in_use & EV5_FA ) { if ( in_use & EV5_FM ) goto done ; in_use |= EV5_FM ; } else in_use |= EV5_FA | EV5_FAM ; break ; case EV5_FA : if ( in_use & EV5_FA ) goto done ; in_use |= EV5_FA ; break ; case EV5_FM : if ( in_use & EV5_FM ) goto done ; in_use |= EV5_FM ; break ; case EV5_NONE : break ; default : gcc_unreachable ( ) ; } len += 4 ; if ( GET_CODE ( insn ) == JUMP_INSN ) goto next_and_done ; next : insn = next_nonnote_insn ( insn ) ; if ( ! insn || ! INSN_P ( insn ) ) goto done ; if ( GET_MODE ( insn ) == TImode ) goto done ; if ( GET_CODE ( insn ) == CLOBBER || GET_CODE ( insn ) == USE ) goto next ; } next_and_done : insn = next_nonnote_insn ( insn ) ; done : * plen = len ; * pin_use = in_use ; return insn ; } </s>

IN_USE is a mask of the slots currently filled within the insn group . The mask bits come from alphaev5_pipe above . If EV5_E01 is set , then the insn in EV5_E0 can be swapped by the hardware into EV5_E1 . LEN is , of course , the length of the group in bytes .


<s> static int alpha_adjust_cost ( rtx insn , rtx link , rtx dep_insn , int cost ) { enum attr_type insn_type , dep_insn_type ; if ( REG_NOTE_KIND ( link ) != 0 ) return cost ; if ( recog_memoized ( insn ) < 0 || recog_memoized ( dep_insn ) < 0 ) return cost ; insn_type = get_attr_type ( insn ) ; dep_insn_type = get_attr_type ( dep_insn ) ; if ( dep_insn_type == TYPE_ILD || dep_insn_type == TYPE_FLD || dep_insn_type == TYPE_LDSYM ) cost += alpha_memory_latency - 1 ; return cost ; } </s>

Adjust the cost of a scheduling dependency . Return the new cost of a dependency LINK or INSN on DEP_INSN . COST is the current cost .


<s> static void alpha_align_insns ( unsigned int max_align , rtx ( * next_group ) ( rtx , int * , int * ) , rtx ( * next_nop ) ( int * ) ) { unsigned int align ; int ofs ; int prev_in_use , in_use , len , ldgp ; rtx i , next ; shorten_branches ( get_insns ( ) ) ; if ( align_functions < 4 ) align = 4 ; else if ( ( unsigned int ) align_functions < max_align ) align = align_functions ; else align = max_align ; ofs = prev_in_use = 0 ; i = get_insns ( ) ; if ( GET_CODE ( i ) == NOTE ) i = next_nonnote_insn ( i ) ; ldgp = alpha_function_needs_gp ? 8 : 0 ; while ( i ) { next = ( * next_group ) ( i , & in_use , & len ) ; if ( GET_CODE ( i ) == CODE_LABEL ) { unsigned int new_align = 1 << label_to_alignment ( i ) ; if ( new_align >= align ) { align = new_align < max_align ? new_align : max_align ; ofs = 0 ; } else if ( ofs & ( new_align - 1 ) ) ofs = ( ofs | ( new_align - 1 ) ) + 1 ; gcc_assert ( ! len ) ; } else if ( in_use == 0 ) { if ( len < 0 ) { ofs = 0 ; align = 4 ; len = 0 ; } } else if ( ( int ) align < len ) { unsigned int new_log_align = len > 8 ? 4 : 3 ; rtx prev , where ; where = prev = prev_nonnote_insn ( i ) ; if ( ! where || GET_CODE ( where ) != CODE_LABEL ) where = i ; if ( ! ( TARGET_EXPLICIT_RELOCS && prev && GET_CODE ( prev ) == CALL_INSN ) ) { emit_insn_before ( gen_realign ( GEN_INT ( new_log_align ) ) , where ) ; align = 1 << new_log_align ; ofs = 0 ; } } else if ( ldgp > 0 ) ldgp -= len ; else if ( ofs + len > ( int ) align ) { int nop_count = ( align - ofs ) / 4 ; rtx where ; where = prev_nonnote_insn ( i ) ; if ( where ) { if ( GET_CODE ( where ) == CODE_LABEL ) { rtx where2 = prev_nonnote_insn ( where ) ; if ( where2 && GET_CODE ( where2 ) == JUMP_INSN ) where = where2 ; } else if ( GET_CODE ( where ) == INSN ) where = i ; } else where = i ; do emit_insn_before ( ( * next_nop ) ( & prev_in_use ) , where ) ; while ( -- nop_count ) ; ofs = 0 ; } ofs = ( ofs + len ) & ( align - 1 ) ; prev_in_use = in_use ; i = next ; } } </s>

The instruction group alignment main loop .


<s> enum avms_arg_type alpha_arg_type ( enum machine_mode mode ) { switch ( mode ) { case SFmode : return TARGET_FLOAT_VAX ? FF : FS ; case DFmode : return TARGET_FLOAT_VAX ? FD : FT ; default : return I64 ; } } </s>

Return the VMS argument type corresponding to MODE .


<s> static bool alpha_cannot_copy_insn_p ( rtx insn ) { if ( ! reload_completed || ! TARGET_EXPLICIT_RELOCS ) return false ; if ( recog_memoized ( insn ) >= 0 ) return get_attr_cannot_copy ( insn ) ; else return false ; } </s>

Indicate that INSN can not be duplicated . This is true for any insn that we 've marked with gpdisp relocs , since those have to stay in 1-1 correspondence with one another . Technically we could copy them if we could set up a mapping from one sequence number to another , across the set of insns to be duplicated . This seems overly complicated and error-prone since interblock motion from sched-ebb could move one of the pair of insns to a different block . Also can not allow jsr insns to be duplicated . If they throw exceptions , then they 'll be in a different block from their ldgp . Which could lead the bb reorder code to think that it would be ok to copy just the block containing the call and branch to the block containing the ldgp .


<s> static bool alpha_cannot_force_const_mem ( rtx x ) { enum rtx_code code = GET_CODE ( x ) ; return code == SYMBOL_REF || code == LABEL_REF || code == CONST ; } </s>

Primarily this is required for TLS symbols , but given that our move patterns * ought * to be able to handle any symbol at any time , we should never be spilling symbolic operands to the constant pool , ever .


<s> bool alpha_const_double_ok_for_letter_p ( rtx value , int c ) { switch ( c ) { case 'G' : return ( GET_MODE_CLASS ( GET_MODE ( value ) ) == MODE_FLOAT && value == CONST0_RTX ( GET_MODE ( value ) ) ) ; case 'H' : return ( GET_MODE ( value ) == VOIDmode && zap_mask ( CONST_DOUBLE_LOW ( value ) ) && zap_mask ( CONST_DOUBLE_HIGH ( value ) ) ) ; default : return false ; } } </s>

Implements CONST_DOUBLE_OK_FOR_LETTER_P . Return true if VALUE matches for C in [ GH ] .


<s> bool alpha_const_ok_for_letter_p ( HOST_WIDE_INT value , int c ) { switch ( c ) { case 'I' : return ( unsigned HOST_WIDE_INT ) value < 0x100 ; case 'J' : return value == 0 ; case 'K' : return ( unsigned HOST_WIDE_INT ) ( value + 0x8000 ) < 0x10000 ; case 'L' : return ( ( value & 0xffff ) == 0 && ( ( value ) >> 31 == - 1 || value >> 31 == 0 ) ) ; case 'M' : return zap_mask ( value ) ; case 'N' : return ( unsigned HOST_WIDE_INT ) ( ~ value ) < 0x100 ; case 'O' : return ( unsigned HOST_WIDE_INT ) ( - value ) < 0x100 ; case 'P' : return value == 1 || value == 2 || value == 3 ; default : return false ; } } </s>

Implements CONST_OK_FOR_LETTER_P . Return true if the value matches the range defined for C in [ I-P ] .


<s> static void alpha_elf_select_rtx_section ( enum machine_mode mode , rtx x , unsigned HOST_WIDE_INT align ) { if ( TARGET_SMALL_DATA && GET_MODE_SIZE ( mode ) <= g_switch_value ) sdata_section ( ) ; else default_elf_select_rtx_section ( mode , x , align ) ; } </s>

Switch to the section to which we should output X . The only thing special we do here is to honor small data .


<s> rtx alpha_emit_setcc ( enum rtx_code code ) { enum rtx_code cmp_code ; rtx op0 = alpha_compare . op0 , op1 = alpha_compare . op1 ; int fp_p = alpha_compare . fp_p ; rtx tmp ; memset ( & alpha_compare , 0 , sizeof ( alpha_compare ) ) ; if ( fp_p && GET_MODE ( op0 ) == TFmode ) { op0 = alpha_emit_xfloating_compare ( & code , op0 , op1 ) ; op1 = const0_rtx ; fp_p = 0 ; } if ( fp_p && ! TARGET_FIX ) return NULL_RTX ; cmp_code = UNKNOWN ; switch ( code ) { case EQ : case LE : case LT : case LEU : case LTU : case UNORDERED : if ( fp_p ) cmp_code = code , code = NE ; break ; case NE : if ( ! fp_p && op1 == const0_rtx ) break ; case ORDERED : cmp_code = reverse_condition ( code ) ; code = EQ ; break ; case GE : case GT : case GEU : case GTU : if ( ! fp_p && op1 == const0_rtx ) break ; code = swap_condition ( code ) ; if ( fp_p ) cmp_code = code , code = NE ; tmp = op0 , op0 = op1 , op1 = tmp ; break ; default : gcc_unreachable ( ) ; } if ( ! fp_p ) { if ( ! register_operand ( op0 , DImode ) ) op0 = force_reg ( DImode , op0 ) ; if ( ! reg_or_8bit_operand ( op1 , DImode ) ) op1 = force_reg ( DImode , op1 ) ; } if ( cmp_code != UNKNOWN ) { enum machine_mode mode = fp_p ? DFmode : DImode ; tmp = gen_reg_rtx ( mode ) ; emit_insn ( gen_rtx_SET ( VOIDmode , tmp , gen_rtx_fmt_ee ( cmp_code , mode , op0 , op1 ) ) ) ; op0 = fp_p ? gen_lowpart ( DImode , tmp ) : tmp ; op1 = const0_rtx ; } return gen_rtx_fmt_ee ( code , DImode , op0 , op1 ) ; } </s>

Certain simplifications can be done to make invalid setcc operations valid . Return the final comparison , or NULL if we ca n't work .


<s> static rtx alpha_emit_set_const ( rtx target , enum machine_mode mode , HOST_WIDE_INT c , int n , bool no_output ) { enum machine_mode orig_mode = mode ; rtx orig_target = target ; rtx result = 0 ; int i ; if ( no_new_pseudos && mode == SImode && GET_CODE ( target ) == REG && REGNO ( target ) < FIRST_PSEUDO_REGISTER ) { result = alpha_emit_set_const_1 ( target , mode , c , 1 , no_output ) ; if ( result ) return result ; target = no_output ? NULL : gen_lowpart ( DImode , target ) ; mode = DImode ; } else if ( mode == V8QImode || mode == V4HImode || mode == V2SImode ) { target = no_output ? NULL : gen_lowpart ( DImode , target ) ; mode = DImode ; } for ( i = 1 ; i <= n ; i ++ ) { result = alpha_emit_set_const_1 ( target , mode , c , i , no_output ) ; if ( result ) { rtx insn , set ; if ( no_output ) return result ; insn = get_last_insn ( ) ; set = single_set ( insn ) ; if ( ! CONSTANT_P ( SET_SRC ( set ) ) ) set_unique_reg_note ( get_last_insn ( ) , REG_EQUAL , GEN_INT ( c ) ) ; break ; } } if ( result ) { if ( result == target ) result = orig_target ; else if ( mode != orig_mode ) result = gen_lowpart ( orig_mode , result ) ; } return result ; } </s>

Try to output insns to set TARGET equal to the constant C if it can be done in less than N insns . Do all computations in MODE . Returns the place where the output has been placed if it can be done and the insns have been emitted . If it would take more than N insns , zero is returned and no insns and emitted .


Having failed to find a 3 insn sequence in alpha_emit_set_const , fall back to a straight forward decomposition . We do this to avoid exponential run times encountered when looking for longer sequences with alpha_emit_set_const .


<s> static rtx alpha_emit_xfloating_compare ( enum rtx_code * pcode , rtx op0 , rtx op1 ) { enum rtx_code cmp_code , res_code ; rtx func , out , operands [ 2 ] ; cmp_code = * pcode ; switch ( cmp_code ) { case UNORDERED : cmp_code = EQ ; res_code = LT ; break ; case ORDERED : cmp_code = EQ ; res_code = GE ; break ; case NE : res_code = NE ; break ; case EQ : case LT : case GT : case LE : case GE : res_code = GT ; break ; default : gcc_unreachable ( ) ; } * pcode = res_code ; func = alpha_lookup_xfloating_lib_func ( cmp_code ) ; operands [ 0 ] = op0 ; operands [ 1 ] = op1 ; out = gen_reg_rtx ( DImode ) ; alpha_emit_xfloating_libcall ( func , out , operands , 2 , gen_rtx_fmt_ee ( cmp_code , CCmode , op0 , op1 ) ) ; return out ; } </s>

Emit an X_floating library function call for a comparison .


<s> static void alpha_emit_xfloating_libcall ( rtx func , rtx target , rtx operands [ ] , int noperands , rtx equiv ) { rtx usage = NULL_RTX , tmp , reg ; int regno = 16 , i ; start_sequence ( ) ; for ( i = 0 ; i < noperands ; ++ i ) { switch ( GET_MODE ( operands [ i ] ) ) { case TFmode : reg = gen_rtx_REG ( TFmode , regno ) ; regno += 2 ; break ; case DFmode : reg = gen_rtx_REG ( DFmode , regno + 32 ) ; regno += 1 ; break ; case VOIDmode : gcc_assert ( GET_CODE ( operands [ i ] ) == CONST_INT ) ; case DImode : reg = gen_rtx_REG ( DImode , regno ) ; regno += 1 ; break ; default : gcc_unreachable ( ) ; } emit_move_insn ( reg , operands [ i ] ) ; usage = alloc_EXPR_LIST ( 0 , gen_rtx_USE ( VOIDmode , reg ) , usage ) ; } switch ( GET_MODE ( target ) ) { case TFmode : reg = gen_rtx_REG ( TFmode , 16 ) ; break ; case DFmode : reg = gen_rtx_REG ( DFmode , 32 ) ; break ; case DImode : reg = gen_rtx_REG ( DImode , 0 ) ; break ; default : gcc_unreachable ( ) ; } tmp = gen_rtx_MEM ( QImode , func ) ; tmp = emit_call_insn ( GEN_CALL_VALUE ( reg , tmp , const0_rtx , const0_rtx , const0_rtx ) ) ; CALL_INSN_FUNCTION_USAGE ( tmp ) = usage ; CONST_OR_PURE_CALL_P ( tmp ) = 1 ; tmp = get_insns ( ) ; end_sequence ( ) ; emit_libcall_block ( tmp , target , reg , equiv ) ; } </s>

Emit an X_floating library function call . Note that these functions do not follow normal calling conventions : TFmode arguments are passed in two integer registers ( as opposed to indirect ) ; TFmode return values appear in R16+R17 . FUNC is the function name to call . TARGET is where the output belongs . OPERANDS are the inputs . NOPERANDS is the count of inputs . EQUIV is the expression equivalent for the function .


<s>
void
alpha_end_function
(
FILE
*
file
,
const
char
*
fnname
,
tree
decl
ATTRIBUTE_UNUSED
)
{
alpha_write_linkage
(
file
,
fnname
,
decl
)
;
if
(
!
TARGET_ABI_UNICOSMK
&&
!
flag_inhibit_size_directive
)
{
fputs
(
"\t.end "
,
file
)
;
assemble_name
(
file
,
fnname
)
;
putc
(
'\n'
,
file
)
;
}
inside_function
=
FALSE
;
if
(
TARGET_ABI_UNICOSMK
)
{
unicosmk_output_ssib
(
file
,
fnname
)
;
unicosmk_output_deferred_case_vectors
(
file
)
;
}
}
</s>

Output the rest of the textual info surrounding the epilogue .


<s>
static
rtx
alpha_expand_builtin
(
tree
exp
,
rtx
target
,
rtx
subtarget
ATTRIBUTE_UNUSED
,
enum
machine_mode
mode
ATTRIBUTE_UNUSED
,
int
ignore
ATTRIBUTE_UNUSED
)
{
tree
fndecl
=
TREE_OPERAND
(
TREE_OPERAND
(
exp
,
0
)
,
0
)
;
unsigned
int
fcode
=
DECL_FUNCTION_CODE
(
fndecl
)
;
tree
arglist
=
TREE_OPERAND
(
exp
,
1
)
;
enum
insn_code
icode
;
rtx
op
[
MAX_ARGS
]
,
pat
;
int
arity
;
bool
nonvoid
;
if
(
fcode
>=
ALPHA_BUILTIN_max
)
internal_error
(
"bad builtin fcode"
)
;
icode
=
code_for_builtin
[
fcode
]
;
if
(
icode
==
0
)
internal_error
(
"bad builtin fcode"
)
;
nonvoid
=
TREE_TYPE
(
TREE_TYPE
(
fndecl
)
)
!=
void_type_node
;
for
(
arglist
=
TREE_OPERAND
(
exp
,
1
)
,
arity
=
0
;
arglist
;
arglist
=
TREE_CHAIN
(
arglist
)
,
arity
++
)
{
const
struct
insn_operand_data
*
insn_op
;
tree
arg
=
TREE_VALUE
(
arglist
)
;
if
(
arg
==
error_mark_node
)
return
NULL_RTX
;
if
(
arity
>
MAX_ARGS
)
return
NULL_RTX
;
insn_op
=
&
insn_data
[
icode
]
.
operand
[
arity
+
nonvoid
]
;
op
[
arity
]
=
expand_expr
(
arg
,
NULL_RTX
,
insn_op
->
mode
,
0
)
;
if
(
!
(
*
insn_op
->
predicate
)
(
op
[
arity
]
,
insn_op
->
mode
)
)
op
[
arity
]
=
copy_to_mode_reg
(
insn_op
->
mode
,
op
[
arity
]
)
;
}
if
(
nonvoid
)
{
enum
machine_mode
tmode
=
insn_data
[
icode
]
.
operand
[
0
]
.
mode
;
if
(
!
target
||
GET_MODE
(
target
)
!=
tmode
||
!
(
*
insn_data
[
icode
]
.
operand
[
0
]
.
predicate
)
(
target
,
tmode
)
)
target
=
gen_reg_rtx
(
tmode
)
;
}
switch
(
arity
)
{
case
0
:
pat
=
GEN_FCN
(
icode
)
(
target
)
;
break
;
case
1
:
if
(
nonvoid
)
pat
=
GEN_FCN
(
icode
)
(
target
,
op
[
0
]
)
;
else
pat
=
GEN_FCN
(
icode
)
(
op
[
0
]
)
;
break
;
case
2
:
pat
=
GEN_FCN
(
icode
)
(
target
,
op
[
0
]
,
op
[
1
]
)
;
break
;
default
:
gcc_unreachable
(
)
;
}
if
(
!
pat
)
return
NULL_RTX
;
emit_insn
(
pat
)
;
if
(
nonvoid
)
return
target
;
else
return
const0_rtx
;
}
</s>

Expand an expression EXP that calls a built-in function , with result going to TARGET if that 's convenient ( and in mode MODE if that 's convenient ) . SUBTARGET may be used as the target for computing one of EXP 's operands . IGNORE is nonzero if the value is to be ignored .


<s> bool alpha_expand_mov ( enum machine_mode mode , rtx * operands ) { if ( GET_CODE ( operands [ 0 ] ) == MEM && ! reg_or_0_operand ( operands [ 1 ] , mode ) ) operands [ 1 ] = force_reg ( mode , operands [ 1 ] ) ; if ( mode == Pmode && symbolic_operand ( operands [ 1 ] , mode ) ) { rtx tmp ; tmp = alpha_legitimize_address ( operands [ 1 ] , operands [ 0 ] , mode ) ; if ( tmp ) { if ( tmp == operands [ 0 ] ) return true ; operands [ 1 ] = tmp ; return false ; } } if ( ! CONSTANT_P ( operands [ 1 ] ) || input_operand ( operands [ 1 ] , mode ) ) return false ; if ( GET_CODE ( operands [ 1 ] ) == CONST_INT || GET_CODE ( operands [ 1 ] ) == CONST_DOUBLE || GET_CODE ( operands [ 1 ] ) == CONST_VECTOR ) { if ( alpha_split_const_mov ( mode , operands ) ) return true ; } operands [ 1 ] = force_const_mem ( mode , operands [ 1 ] ) ; if ( reload_in_progress ) { emit_move_insn ( operands [ 0 ] , XEXP ( operands [ 1 ] , 0 ) ) ; operands [ 1 ] = copy_rtx ( operands [ 1 ] ) ; XEXP ( operands [ 1 ] , 0 ) = operands [ 0 ] ; } else operands [ 1 ] = validize_mem ( operands [ 1 ] ) ; return false ; } </s>

Expand a move instruction ; return true if all work is done . We do n't handle non-bwx subword loads here .


<s> void alpha_expand_movmisalign ( enum machine_mode mode , rtx * operands ) { if ( MEM_P ( operands [ 1 ] ) ) { rtx tmp ; if ( register_operand ( operands [ 0 ] , mode ) ) tmp = operands [ 0 ] ; else tmp = gen_reg_rtx ( mode ) ; alpha_expand_unaligned_load ( tmp , operands [ 1 ] , 8 , 0 , 0 ) ; if ( tmp != operands [ 0 ] ) emit_move_insn ( operands [ 0 ] , tmp ) ; } else if ( MEM_P ( operands [ 0 ] ) ) { if ( ! reg_or_0_operand ( operands [ 1 ] , mode ) ) operands [ 1 ] = force_reg ( mode , operands [ 1 ] ) ; alpha_expand_unaligned_store ( operands [ 0 ] , operands [ 1 ] , 8 , 0 ) ; } else gcc_unreachable ( ) ; } </s>

Implement the movmisalign patterns . One of the operands is a memory that is not naturally aligned . Emit instructions to load it .


<s> static void alpha_expand_unaligned_load_words ( rtx * out_regs , rtx smem , HOST_WIDE_INT words , HOST_WIDE_INT ofs ) { rtx const im8 = GEN_INT ( - 8 ) ; rtx const i64 = GEN_INT ( 64 ) ; rtx ext_tmps [ MAX_MOVE_WORDS ] , data_regs [ MAX_MOVE_WORDS + 1 ] ; rtx sreg , areg , tmp , smema ; HOST_WIDE_INT i ; smema = XEXP ( smem , 0 ) ; if ( GET_CODE ( smema ) == LO_SUM ) smema = force_reg ( Pmode , smema ) ; for ( i = 0 ; i < words ; ++ i ) { data_regs [ i ] = out_regs [ i ] ; ext_tmps [ i ] = gen_reg_rtx ( DImode ) ; } data_regs [ words ] = gen_reg_rtx ( DImode ) ; if ( ofs != 0 ) smem = adjust_address ( smem , GET_MODE ( smem ) , ofs ) ; for ( i = 0 ; i < words ; ++ i ) { tmp = change_address ( smem , DImode , gen_rtx_AND ( DImode , plus_constant ( smema , 8 * i ) , im8 ) ) ; set_mem_alias_set ( tmp , 0 ) ; emit_move_insn ( data_regs [ i ] , tmp ) ; } tmp = change_address ( smem , DImode , gen_rtx_AND ( DImode , plus_constant ( smema , 8 * words - 1 ) , im8 ) ) ; set_mem_alias_set ( tmp , 0 ) ; emit_move_insn ( data_regs [ words ] , tmp ) ; sreg = copy_addr_to_reg ( smema ) ; areg = expand_binop ( DImode , and_optab , sreg , GEN_INT ( 7 ) , NULL , 1 , OPTAB_WIDEN ) ; if ( WORDS_BIG_ENDIAN ) emit_move_insn ( sreg , plus_constant ( sreg , 7 ) ) ; for ( i = 0 ; i < words ; ++ i ) { if ( WORDS_BIG_ENDIAN ) { emit_insn ( gen_extqh_be ( data_regs [ i ] , data_regs [ i ] , sreg ) ) ; emit_insn ( gen_extxl_be ( ext_tmps [ i ] , data_regs [ i + 1 ] , i64 , sreg ) ) ; } else { emit_insn ( gen_extxl_le ( data_regs [ i ] , data_regs [ i ] , i64 , sreg ) ) ; emit_insn ( gen_extqh_le ( ext_tmps [ i ] , data_regs [ i + 1 ] , sreg ) ) ; } emit_insn ( gen_rtx_SET ( VOIDmode , ext_tmps [ i ] , gen_rtx_IF_THEN_ELSE ( DImode , gen_rtx_EQ ( DImode , areg , const0_rtx ) , const0_rtx , ext_tmps [ i ] ) ) ) ; } for ( i = 0 ; i < words ; ++ i ) { out_regs [ i ] = expand_binop ( DImode , ior_optab , data_regs [ i ] , ext_tmps [ i ] , data_regs [ i ] , 1 , OPTAB_WIDEN ) ; } } </s>

Load an integral number of consecutive unaligned quadwords .


<s> rtx alpha_expand_zap_mask ( HOST_WIDE_INT value ) { rtx result ; int i ; if ( HOST_BITS_PER_WIDE_INT >= 64 ) { HOST_WIDE_INT mask = 0 ; for ( i = 7 ; i >= 0 ; -- i ) { mask <<= 8 ; if ( ! ( ( value >> i ) & 1 ) ) mask |= 0xff ; } result = gen_int_mode ( mask , DImode ) ; } else { HOST_WIDE_INT mask_lo = 0 , mask_hi = 0 ; gcc_assert ( HOST_BITS_PER_WIDE_INT == 32 ) ; for ( i = 7 ; i >= 4 ; -- i ) { mask_hi <<= 8 ; if ( ! ( ( value >> i ) & 1 ) ) mask_hi |= 0xff ; } for ( i = 3 ; i >= 0 ; -- i ) { mask_lo <<= 8 ; if ( ! ( ( value >> i ) & 1 ) ) mask_lo |= 0xff ; } result = immed_double_const ( mask_lo , mask_hi , DImode ) ; } return result ; } </s>

Returns a mask so that zap ( x , value ) == x & mask .


<s> static void alpha_extract_integer ( rtx x , HOST_WIDE_INT * p0 , HOST_WIDE_INT * p1 ) { HOST_WIDE_INT i0 , i1 ; if ( GET_CODE ( x ) == CONST_VECTOR ) x = simplify_subreg ( DImode , x , GET_MODE ( x ) , 0 ) ; if ( GET_CODE ( x ) == CONST_INT ) { i0 = INTVAL ( x ) ; i1 = - ( i0 < 0 ) ; } else if ( HOST_BITS_PER_WIDE_INT >= 64 ) { i0 = CONST_DOUBLE_LOW ( x ) ; i1 = - ( i0 < 0 ) ; } else { i0 = CONST_DOUBLE_LOW ( x ) ; i1 = CONST_DOUBLE_HIGH ( x ) ; } * p0 = i0 ; * p1 = i1 ; } </s>

Given an integral CONST_INT , CONST_DOUBLE , or CONST_VECTOR , return the low 64 bits .


<s> bool alpha_extra_constraint ( rtx value , int c ) { switch ( c ) { case 'Q' : return normal_memory_operand ( value , VOIDmode ) ; case 'R' : return direct_call_operand ( value , Pmode ) ; case 'S' : return ( GET_CODE ( value ) == CONST_INT && ( unsigned HOST_WIDE_INT ) INTVAL ( value ) < 64 ) ; case 'T' : return GET_CODE ( value ) == HIGH ; case 'U' : return TARGET_ABI_UNICOSMK && symbolic_operand ( value , VOIDmode ) ; case 'W' : return ( GET_CODE ( value ) == CONST_VECTOR && value == CONST0_RTX ( GET_MODE ( value ) ) ) ; default : return false ; } } </s>

Implements CONST_DOUBLE_OK_FOR_LETTER_P . Return true if VALUE matches for C .


<s> static tree alpha_fold_builtin_cmpbge ( unsigned HOST_WIDE_INT opint [ ] , long op_const ) { if ( op_const == 3 ) { int i , val ; for ( i = 0 , val = 0 ; i < 8 ; ++ i ) { unsigned HOST_WIDE_INT c0 = ( opint [ 0 ] >> ( i * 8 ) ) & 0xff ; unsigned HOST_WIDE_INT c1 = ( opint [ 1 ] >> ( i * 8 ) ) & 0xff ; if ( c0 >= c1 ) val |= 1 << i ; } return build_int_cst ( long_integer_type_node , val ) ; } else if ( op_const == 2 && opint [ 1 ] == 0 ) return build_int_cst ( long_integer_type_node , 0xff ) ; return NULL ; } </s>

Fold the builtin for the CMPBGE instruction . This is a vector comparison with an 8 bit output vector . OPINT contains the integer operands ; bit N of OP_CONST is set if OPINT [ N ] is valid .


<s> static tree alpha_fold_builtin_extxx ( tree op [ ] , unsigned HOST_WIDE_INT opint [ ] , long op_const , unsigned HOST_WIDE_INT bytemask , bool is_high ) { long zap_const = 2 ; tree * zap_op = NULL ; if ( op_const & 2 ) { unsigned HOST_WIDE_INT loc ; loc = opint [ 1 ] & 7 ; if ( BYTES_BIG_ENDIAN ) loc ^= 7 ; loc *= 8 ; if ( loc != 0 ) { if ( op_const & 1 ) { unsigned HOST_WIDE_INT temp = opint [ 0 ] ; if ( is_high ) temp <<= loc ; else temp >>= loc ; opint [ 0 ] = temp ; zap_const = 3 ; } } else zap_op = op ; } opint [ 1 ] = bytemask ; return alpha_fold_builtin_zapnot ( zap_op , opint , zap_const ) ; } </s>

Fold the builtins for the EXT family of instructions .


<s> static tree alpha_fold_builtin_insxx ( tree op [ ] , unsigned HOST_WIDE_INT opint [ ] , long op_const , unsigned HOST_WIDE_INT bytemask , bool is_high ) { if ( ( op_const & 1 ) && opint [ 0 ] == 0 ) return build_int_cst ( long_integer_type_node , 0 ) ; if ( op_const & 2 ) { unsigned HOST_WIDE_INT temp , loc , byteloc ; tree * zap_op = NULL ; loc = opint [ 1 ] & 7 ; if ( BYTES_BIG_ENDIAN ) loc ^= 7 ; bytemask <<= loc ; temp = opint [ 0 ] ; if ( is_high ) { byteloc = ( 64 - ( loc * 8 ) ) & 0x3f ; if ( byteloc == 0 ) zap_op = op ; else temp >>= byteloc ; bytemask >>= 8 ; } else { byteloc = loc * 8 ; if ( byteloc == 0 ) zap_op = op ; else temp <<= byteloc ; } opint [ 0 ] = temp ; opint [ 1 ] = bytemask ; return alpha_fold_builtin_zapnot ( zap_op , opint , op_const ) ; } return NULL ; } </s>

Fold the builtins for the INS family of instructions .


<s> static tree alpha_fold_builtin_zapnot ( tree * op , unsigned HOST_WIDE_INT opint [ ] , long op_const ) { if ( op_const & 2 ) { unsigned HOST_WIDE_INT mask = 0 ; int i ; for ( i = 0 ; i < 8 ; ++ i ) if ( ( opint [ 1 ] >> i ) & 1 ) mask |= ( unsigned HOST_WIDE_INT ) 0xff << ( i * 8 ) ; if ( op_const & 1 ) return build_int_cst ( long_integer_type_node , opint [ 0 ] & mask ) ; if ( op ) return fold ( build2 ( BIT_AND_EXPR , long_integer_type_node , op [ 0 ] , build_int_cst ( long_integer_type_node , mask ) ) ) ; } else if ( ( op_const & 1 ) && opint [ 0 ] == 0 ) return build_int_cst ( long_integer_type_node , 0 ) ; return NULL ; } </s>

Fold the builtin for the ZAPNOT instruction . This is essentially a specialized form of an AND operation . Other byte manipulation instructions are defined in terms of this instruction , so this is also used as a subroutine for other builtins . OP contains the tree operands ; OPINT contains the extracted integer values . Bit N of OP_CONST it set if OPINT [ N ] is valid . OP may be null if only OPINT may be considered .


<s> rtx alpha_gp_save_rtx ( void ) { rtx seq , m = cfun -> machine -> gp_save_rtx ; if ( m == NULL ) { start_sequence ( ) ; m = assign_stack_local ( DImode , UNITS_PER_WORD , BITS_PER_WORD ) ; m = validize_mem ( m ) ; emit_move_insn ( m , pic_offset_table_rtx ) ; seq = get_insns ( ) ; end_sequence ( ) ; emit_insn_after ( seq , entry_of_function ( ) ) ; cfun -> machine -> gp_save_rtx = m ; } return m ; } </s>

Return or create a pseudo containing the gp value for the current function . Needed only if TARGET_LD_BUGGY_LDGP .


<s>
static
bool
alpha_handle_option
(
size_t
code
,
const
char
*
arg
,
int
value
)
{
switch
(
code
)
{
case
OPT_mfp_regs
:
if
(
value
==
0
)
target_flags
|=
MASK_SOFT_FP
;
break
;
case
OPT_mieee
:
case
OPT_mieee_with_inexact
:
target_flags
|=
MASK_IEEE_CONFORMANT
;
break
;
case
OPT_mtls_size_
:
if
(
value
!=
16
&&
value
!=
32
&&
value
!=
64
)
error
(
"bad value %qs for -mtls-size switch"
,
arg
)
;
break
;
}
return
true
;
}
</s>


<s> void alpha_initialize_trampoline ( rtx tramp , rtx fnaddr , rtx cxt , int fnofs , int cxtofs , int jmpofs ) { rtx temp , temp1 , addr ; enum machine_mode mode = TARGET_ABI_OPEN_VMS ? Pmode : ptr_mode ; fnaddr = convert_memory_address ( mode , fnaddr ) ; cxt = convert_memory_address ( mode , cxt ) ; addr = memory_address ( mode , plus_constant ( tramp , fnofs ) ) ; emit_move_insn ( gen_rtx_MEM ( mode , addr ) , fnaddr ) ; addr = memory_address ( mode , plus_constant ( tramp , cxtofs ) ) ; emit_move_insn ( gen_rtx_MEM ( mode , addr ) , cxt ) ; if ( 0 && jmpofs >= 0 ) { temp = force_operand ( plus_constant ( tramp , jmpofs + 4 ) , NULL_RTX ) ; temp = expand_binop ( DImode , sub_optab , fnaddr , temp , temp , 1 , OPTAB_WIDEN ) ; temp = expand_shift ( RSHIFT_EXPR , Pmode , temp , build_int_cst ( NULL_TREE , 2 ) , NULL_RTX , 1 ) ; temp = expand_and ( SImode , gen_lowpart ( SImode , temp ) , GEN_INT ( 0x3fff ) , 0 ) ; addr = memory_address ( SImode , plus_constant ( tramp , jmpofs ) ) ; temp1 = force_reg ( SImode , gen_rtx_MEM ( SImode , addr ) ) ; temp1 = expand_and ( SImode , temp1 , GEN_INT ( 0xffffc000 ) , NULL_RTX ) ; temp1 = expand_binop ( SImode , ior_optab , temp1 , temp , temp1 , 1 , OPTAB_WIDEN ) ; emit_move_insn ( gen_rtx_MEM ( SImode , addr ) , temp1 ) ; } emit_library_call ( init_one_libfunc ( "__enable_execute_stack" ) , 0 , VOIDmode , 1 , tramp , Pmode ) ; if ( jmpofs >= 0 ) emit_insn ( gen_imb ( ) ) ; } </s>

Emit RTL insns to initialize the variable parts of a trampoline at TRAMP . FNADDR is an RTX for the address of the function 's pure code . CXT is an RTX for the static chain value for the function . The three offset parameters are for the individual template 's layout . A JMPOFS < 0 indicates that the trampoline does not contain instructions at all . We assume here that a function will be called many more times than its address is taken ( e.g. , it might be passed to qsort ) , so we take the trouble to initialize the `` hint '' field in the JMP insn . Note that the hint field is PC ( new ) + 4 * bits 13:0 .


<s> HOST_WIDE_INT alpha_initial_elimination_offset ( unsigned int from , unsigned int to ATTRIBUTE_UNUSED ) { HOST_WIDE_INT ret ; ret = alpha_sa_size ( ) ; ret += ALPHA_ROUND ( current_function_outgoing_args_size ) ; switch ( from ) { case FRAME_POINTER_REGNUM : break ; case ARG_POINTER_REGNUM : ret += ( ALPHA_ROUND ( get_frame_size ( ) + current_function_pretend_args_size ) - current_function_pretend_args_size ) ; break ; default : gcc_unreachable ( ) ; } return ret ; } </s>

Define the offset between two registers , one to be eliminated , and the other its replacement , at the start of a routine .


<s> static bool alpha_in_small_data_p ( tree exp ) { if ( TREE_CODE ( exp ) == STRING_CST ) return false ; if ( TREE_CODE ( exp ) == FUNCTION_DECL ) return false ; if ( TREE_CODE ( exp ) == VAR_DECL && DECL_SECTION_NAME ( exp ) ) { const char * section = TREE_STRING_POINTER ( DECL_SECTION_NAME ( exp ) ) ; if ( strcmp ( section , ".sdata" ) == 0 || strcmp ( section , ".sbss" ) == 0 ) return true ; } else { HOST_WIDE_INT size = int_size_in_bytes ( TREE_TYPE ( exp ) ) ; if ( size > 0 && ( unsigned HOST_WIDE_INT ) size <= g_switch_value ) return true ; } return false ; } </s>

Return true if EXP should be placed in the small data section .


<s> bool alpha_legitimate_address_p ( enum machine_mode mode , rtx x , int strict ) { if ( mode == DImode && GET_CODE ( x ) == AND && GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT && INTVAL ( XEXP ( x , 1 ) ) == - 8 ) x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == SUBREG && ( GET_MODE_SIZE ( GET_MODE ( x ) ) < GET_MODE_SIZE ( GET_MODE ( SUBREG_REG ( x ) ) ) ) ) x = SUBREG_REG ( x ) ; if ( REG_P ( x ) && ( strict ? STRICT_REG_OK_FOR_BASE_P ( x ) : NONSTRICT_REG_OK_FOR_BASE_P ( x ) ) ) return true ; if ( CONSTANT_ADDRESS_P ( x ) ) return true ; if ( LINKAGE_SYMBOL_REF_P ( x ) ) return true ; if ( GET_CODE ( x ) == PLUS ) { rtx ofs = XEXP ( x , 1 ) ; x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == SUBREG && ( GET_MODE_SIZE ( GET_MODE ( x ) ) < GET_MODE_SIZE ( GET_MODE ( SUBREG_REG ( x ) ) ) ) ) x = SUBREG_REG ( x ) ; if ( REG_P ( x ) ) { if ( ! strict && NONSTRICT_REG_OK_FP_BASE_P ( x ) && GET_CODE ( ofs ) == CONST_INT ) return true ; if ( ( strict ? STRICT_REG_OK_FOR_BASE_P ( x ) : NONSTRICT_REG_OK_FOR_BASE_P ( x ) ) && CONSTANT_ADDRESS_P ( ofs ) ) return true ; } } else if ( TARGET_EXPLICIT_RELOCS ) { if ( small_symbolic_operand ( x , Pmode ) ) return true ; if ( GET_CODE ( x ) == LO_SUM ) { rtx ofs = XEXP ( x , 1 ) ; x = XEXP ( x , 0 ) ; if ( GET_CODE ( x ) == SUBREG && ( GET_MODE_SIZE ( GET_MODE ( x ) ) < GET_MODE_SIZE ( GET_MODE ( SUBREG_REG ( x ) ) ) ) ) x = SUBREG_REG ( x ) ; if ( ! ( REG_P ( x ) && ( strict ? STRICT_REG_OK_FOR_BASE_P ( x ) : NONSTRICT_REG_OK_FOR_BASE_P ( x ) ) ) ) return false ; if ( local_symbolic_operand ( ofs , Pmode ) || dtp32_symbolic_operand ( ofs , Pmode ) || tp32_symbolic_operand ( ofs , Pmode ) ) return true ; } } return false ; } </s>

legitimate_address_p recognizes an RTL expression that is a valid memory address for an instruction . The MODE argument is the machine mode for the MEM expression that wants to use this address . For Alpha , we have either a constant address or the sum of a register and a constant address , or just a register . For DImode , any of those forms can be surrounded with an AND that clear the low-order three bits ; this is an `` unaligned '' access .


<s> bool alpha_legitimate_constant_p ( rtx x ) { enum machine_mode mode = GET_MODE ( x ) ; HOST_WIDE_INT i0 , i1 ; switch ( GET_CODE ( x ) ) { case CONST : case LABEL_REF : case SYMBOL_REF : case HIGH : return true ; case CONST_DOUBLE : if ( x == CONST0_RTX ( mode ) ) return true ; if ( FLOAT_MODE_P ( mode ) ) return false ; goto do_integer ; case CONST_VECTOR : if ( x == CONST0_RTX ( mode ) ) return true ; if ( GET_MODE_CLASS ( mode ) != MODE_VECTOR_INT ) return false ; if ( GET_MODE_SIZE ( mode ) != 8 ) return false ; goto do_integer ; case CONST_INT : do_integer : if ( TARGET_BUILD_CONSTANTS ) return true ; alpha_extract_integer ( x , & i0 , & i1 ) ; if ( HOST_BITS_PER_WIDE_INT >= 64 || i1 == ( - i0 < 0 ) ) return alpha_emit_set_const_1 ( x , mode , i0 , 3 , true ) != NULL ; return false ; default : return false ; } } </s>

Implement LEGITIMATE_CONSTANT_P . This is all constants for which we are willing to load the value into a register via a move pattern . Normally this is all symbolic constants , integral constants that take three or fewer instructions , and floating-point zero .


<s> rtx alpha_legitimize_reload_address ( rtx x , enum machine_mode mode ATTRIBUTE_UNUSED , int opnum , int type , int ind_levels ATTRIBUTE_UNUSED ) { if ( GET_CODE ( x ) == PLUS && GET_CODE ( XEXP ( x , 0 ) ) == PLUS && GET_CODE ( XEXP ( XEXP ( x , 0 ) , 0 ) ) == REG && GET_CODE ( XEXP ( XEXP ( x , 0 ) , 1 ) ) == CONST_INT && GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT ) { push_reload ( XEXP ( x , 0 ) , NULL_RTX , & XEXP ( x , 0 ) , NULL , BASE_REG_CLASS , GET_MODE ( x ) , VOIDmode , 0 , 0 , opnum , type ) ; return x ; } if ( GET_CODE ( x ) == PLUS && GET_CODE ( XEXP ( x , 0 ) ) == REG && REGNO ( XEXP ( x , 0 ) ) < FIRST_PSEUDO_REGISTER && REGNO_OK_FOR_BASE_P ( REGNO ( XEXP ( x , 0 ) ) ) && GET_CODE ( XEXP ( x , 1 ) ) == CONST_INT ) { HOST_WIDE_INT val = INTVAL ( XEXP ( x , 1 ) ) ; HOST_WIDE_INT low = ( ( val & 0xffff ) ^ 0x8000 ) - 0x8000 ; HOST_WIDE_INT high = ( ( ( val - low ) & 0xffffffff ) ^ 0x80000000 ) - 0x80000000 ; if ( high + low != val ) return NULL_RTX ; x = gen_rtx_PLUS ( GET_MODE ( x ) , gen_rtx_PLUS ( GET_MODE ( x ) , XEXP ( x , 0 ) , GEN_INT ( high ) ) , GEN_INT ( low ) ) ; push_reload ( XEXP ( x , 0 ) , NULL_RTX , & XEXP ( x , 0 ) , NULL , BASE_REG_CLASS , GET_MODE ( x ) , VOIDmode , 0 , 0 , opnum , type ) ; return x ; } return NULL_RTX ; } </s>

Try a machine-dependent way of reloading an illegitimate address operand . If we find one , push the reload and return the new rtx .


<s> static const char * alpha_mangle_fundamental_type ( tree type ) { if ( TYPE_MAIN_VARIANT ( type ) == long_double_type_node && TARGET_LONG_DOUBLE_128 ) return "g" ; return NULL ; } </s>


<s> rtx alpha_need_linkage ( const char * name ATTRIBUTE_UNUSED , int is_local ATTRIBUTE_UNUSED ) { return NULL_RTX ; } </s>

Make ( or fake ) .linkage entry for function call . IS_LOCAL is 0 if name is used in call , 1 if name is used in definition . Return an SYMBOL_REF rtx for the linkage .


<s>
void
alpha_output_filename
(
FILE
*
stream
,
const
char
*
name
)
{
static
int
first_time
=
TRUE
;
if
(
first_time
)
{
first_time
=
FALSE
;
++
num_source_filenames
;
current_function_file
=
name
;
fprintf
(
stream
,
"\t.file\t%d "
,
num_source_filenames
)
;
output_quoted_string
(
stream
,
name
)
;
fprintf
(
stream
,
"\n"
)
;
if
(
!
TARGET_GAS
&&
write_symbols
==
DBX_DEBUG
)
fprintf
(
stream
,
"\t#@stabs\n"
)
;
}
else
if
(
write_symbols
==
DBX_DEBUG
)
return
;
else
if
(
name
!=
current_function_file
&&
strcmp
(
name
,
current_function_file
)
!=
0
)
{
if
(
inside_function
&&
!
TARGET_GAS
)
fprintf
(
stream
,
"\t#.file\t%d "
,
num_source_filenames
)
;
else
{
++
num_source_filenames
;
current_function_file
=
name
;
fprintf
(
stream
,
"\t.file\t%d "
,
num_source_filenames
)
;
}
output_quoted_string
(
stream
,
name
)
;
fprintf
(
stream
,
"\n"
)
;
}
}
</s>

alpha
"\t.file\t%d "
"\n"
"\t#@stabs\n"
0
"\t#.file\t%d "
"\t.file\t%d "
"\n"


<s>
static
void
alpha_output_function_end_prologue
(
FILE
*
file
)
{
if
(
TARGET_ABI_UNICOSMK
)
;
else
if
(
TARGET_ABI_OPEN_VMS
)
fputs
(
"\t.prologue\n"
,
file
)
;
else
if
(
TARGET_ABI_WINDOWS_NT
)
fputs
(
"\t.prologue 0\n"
,
file
)
;
else
if
(
!
flag_inhibit_size_directive
)
fprintf
(
file
,
"\t.prologue %d\n"
,
alpha_function_needs_gp
||
current_function_is_thunk
)
;
}
</s>

Emit the .prologue note at the scheduled end of the prologue .

alpha
"\t.prologue\n"
"\t.prologue 0\n"
"\t.prologue %d\n"


<s> static void alpha_output_mi_thunk_osf ( FILE * file , tree thunk_fndecl ATTRIBUTE_UNUSED , HOST_WIDE_INT delta , HOST_WIDE_INT vcall_offset , tree function ) { HOST_WIDE_INT hi , lo ; rtx this , insn , funexp ; reset_block_changes ( ) ; emit_insn ( gen_prologue_ldgp ( ) ) ; emit_note ( NOTE_INSN_PROLOGUE_END ) ; if ( aggregate_value_p ( TREE_TYPE ( TREE_TYPE ( function ) ) , function ) ) this = gen_rtx_REG ( Pmode , 17 ) ; else this = gen_rtx_REG ( Pmode , 16 ) ; lo = ( ( delta & 0xffff ) ^ 0x8000 ) - 0x8000 ; hi = ( ( ( delta - lo ) & 0xffffffff ) ^ 0x80000000 ) - 0x80000000 ; if ( hi + lo == delta ) { if ( hi ) emit_insn ( gen_adddi3 ( this , this , GEN_INT ( hi ) ) ) ; if ( lo ) emit_insn ( gen_adddi3 ( this , this , GEN_INT ( lo ) ) ) ; } else { rtx tmp = alpha_emit_set_long_const ( gen_rtx_REG ( Pmode , 0 ) , delta , - ( delta < 0 ) ) ; emit_insn ( gen_adddi3 ( this , this , tmp ) ) ; } if ( vcall_offset ) { rtx tmp , tmp2 ; tmp = gen_rtx_REG ( Pmode , 0 ) ; emit_move_insn ( tmp , gen_rtx_MEM ( Pmode , this ) ) ; lo = ( ( vcall_offset & 0xffff ) ^ 0x8000 ) - 0x8000 ; hi = ( ( ( vcall_offset - lo ) & 0xffffffff ) ^ 0x80000000 ) - 0x80000000 ; if ( hi + lo == vcall_offset ) { if ( hi ) emit_insn ( gen_adddi3 ( tmp , tmp , GEN_INT ( hi ) ) ) ; } else { tmp2 = alpha_emit_set_long_const ( gen_rtx_REG ( Pmode , 1 ) , vcall_offset , - ( vcall_offset < 0 ) ) ; emit_insn ( gen_adddi3 ( tmp , tmp , tmp2 ) ) ; lo = 0 ; } if ( lo ) tmp2 = gen_rtx_PLUS ( Pmode , tmp , GEN_INT ( lo ) ) ; else tmp2 = tmp ; emit_move_insn ( tmp , gen_rtx_MEM ( Pmode , tmp2 ) ) ; emit_insn ( gen_adddi3 ( this , this , tmp ) ) ; } if ( ! TREE_USED ( function ) ) { assemble_external ( function ) ; TREE_USED ( function ) = 1 ; } funexp = XEXP ( DECL_RTL ( function ) , 0 ) ; funexp = gen_rtx_MEM ( FUNCTION_MODE , funexp ) ; insn = emit_call_insn ( gen_sibcall ( funexp , const0_rtx ) ) ; SIBLING_CALL_P ( insn ) = 1 ; insn = get_insns ( ) ; insn_locators_initialize ( ) ; shorten_branches ( insn ) ; final_start_function ( insn , file , 1 ) ; final ( insn , file , 1 ) ; final_end_function ( ) ; } </s>

Emit a tail call to FUNCTION after adjusting THIS by DELTA . In order to avoid the hordes of differences between generated code with and without TARGET_EXPLICIT_RELOCS , and to avoid duplicating lots of code loading up large constants , generate rtl and emit it instead of going straight to text . Not sure why this idea has n't been explored before ...


<s> enum reg_class alpha_preferred_reload_class ( rtx x , enum reg_class class ) { if ( x == CONST0_RTX ( GET_MODE ( x ) ) ) return class ; if ( GET_CODE ( x ) == CONST_INT || GET_CODE ( x ) == CONST_DOUBLE || GET_CODE ( x ) == CONST_VECTOR ) { if ( class == FLOAT_REGS ) return NO_REGS ; if ( class == ALL_REGS ) return GENERAL_REGS ; return class ; } if ( CONSTANT_P ( x ) ) return ( class == ALL_REGS ? GENERAL_REGS : class ) ; return class ; } </s>

On the Alpha , all ( non-symbolic ) constants except zero go into a floating-point register via memory . Note that we can not return anything that is not a subset of CLASS , and that some symbolic constants can not be dropped to memory .


<s> static void alpha_reorg ( void ) { if ( alpha_tp != ALPHA_TP_PROG || flag_exceptions ) alpha_handle_trap_shadows ( ) ; if ( optimize && ! optimize_size && alpha_tp != ALPHA_TP_INSN && flag_schedule_insns_after_reload ) { if ( alpha_tune == PROCESSOR_EV4 ) alpha_align_insns ( 8 , alphaev4_next_group , alphaev4_next_nop ) ; else if ( alpha_tune == PROCESSOR_EV5 ) alpha_align_insns ( 16 , alphaev5_next_group , alphaev5_next_nop ) ; } } </s>


<s> static bool alpha_return_in_memory ( tree type , tree fndecl ATTRIBUTE_UNUSED ) { enum machine_mode mode = VOIDmode ; int size ; if ( type ) { mode = TYPE_MODE ( type ) ; if ( AGGREGATE_TYPE_P ( type ) ) return true ; } size = GET_MODE_SIZE ( mode ) ; switch ( GET_MODE_CLASS ( mode ) ) { case MODE_VECTOR_FLOAT : return true ; case MODE_COMPLEX_FLOAT : size = GET_MODE_UNIT_SIZE ( mode ) ; break ; case MODE_INT : case MODE_FLOAT : case MODE_COMPLEX_INT : case MODE_VECTOR_INT : break ; default : return true ; } return size > UNITS_PER_WORD ; } </s>

Return true if TYPE must be returned in memory , instead of in registers .


<s> static void alpha_sa_mask ( unsigned long * imaskP , unsigned long * fmaskP ) { unsigned long imask = 0 ; unsigned long fmask = 0 ; unsigned int i ; if ( current_function_is_thunk ) { * imaskP = 0 ; * fmaskP = 0 ; return ; } if ( TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK ) imask |= ( 1UL << HARD_FRAME_POINTER_REGNUM ) ; for ( i = 0 ; i < FIRST_PSEUDO_REGISTER ; i ++ ) if ( ! fixed_regs [ i ] && ! call_used_regs [ i ] && regs_ever_live [ i ] && i != REG_RA && ( ! TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM ) ) { if ( i < 32 ) imask |= ( 1UL << i ) ; else fmask |= ( 1UL << ( i - 32 ) ) ; } if ( current_function_calls_eh_return ) { for ( i = 0 ; ; ++ i ) { unsigned regno = EH_RETURN_DATA_REGNO ( i ) ; if ( regno == INVALID_REGNUM ) break ; imask |= 1UL << regno ; } } if ( imask || fmask || alpha_ra_ever_killed ( ) ) imask |= ( 1UL << REG_RA ) ; * imaskP = imask ; * fmaskP = fmask ; } </s>

Compute register masks for saved registers .


<s> static bool alpha_scalar_mode_supported_p ( enum machine_mode mode ) { switch ( mode ) { case QImode : case HImode : case SImode : case DImode : case TImode : return true ; case SFmode : case DFmode : return true ; case TFmode : return TARGET_HAS_XFLOATING_LIBS ; default : return false ; } } </s>

The scalar modes supported differs from the default check-what-c-supports version in that sometimes TFmode is available even when long double indicates only DFmode . On unicosmk , we have the situation that HImode does n't map to any C type , but of course we still support that .


<s> static void alpha_setup_incoming_varargs ( CUMULATIVE_ARGS * pcum , enum machine_mode mode , tree type , int * pretend_size , int no_rtl ) { CUMULATIVE_ARGS cum = * pcum ; FUNCTION_ARG_ADVANCE ( cum , mode , type , 1 ) ; if ( cum . num_reg_words < 6 ) { if ( ! no_rtl ) { emit_insn ( gen_umk_mismatch_args ( GEN_INT ( cum . num_reg_words ) ) ) ; emit_insn ( gen_arg_home_umk ( ) ) ; } * pretend_size = 0 ; } if ( cum . num_args < 6 ) { if ( ! no_rtl ) { emit_move_insn ( gen_rtx_REG ( DImode , 1 ) , virtual_incoming_args_rtx ) ; emit_insn ( gen_arg_home ( ) ) ; } * pretend_size = 7 * UNITS_PER_WORD ; } if ( cum >= 6 ) return ; if ( ! no_rtl ) { int count , set = get_varargs_alias_set ( ) ; rtx tmp ; count = cfun -> va_list_gpr_size / UNITS_PER_WORD ; if ( count > 6 - cum ) count = 6 - cum ; gcc_assert ( ( VA_LIST_MAX_FPR_SIZE & 3 ) == 3 ) ; if ( cfun -> va_list_fpr_size & 1 ) { tmp = gen_rtx_MEM ( BLKmode , plus_constant ( virtual_incoming_args_rtx , ( cum + 6 ) * UNITS_PER_WORD ) ) ; MEM_NOTRAP_P ( tmp ) = 1 ; set_mem_alias_set ( tmp , set ) ; move_block_from_reg ( 16 + cum , tmp , count ) ; } if ( cfun -> va_list_fpr_size & 2 ) { tmp = gen_rtx_MEM ( BLKmode , plus_constant ( virtual_incoming_args_rtx , cum * UNITS_PER_WORD ) ) ; MEM_NOTRAP_P ( tmp ) = 1 ; set_mem_alias_set ( tmp , set ) ; move_block_from_reg ( 16 + cum + TARGET_FPREGS * 32 , tmp , count ) ; } } * pretend_size = 12 * UNITS_PER_WORD ; } </s>

Perform any needed actions needed for a function that is receiving a variable number of arguments .


<s> void alpha_set_memflags ( rtx insn , rtx ref ) { rtx * base_ptr ; if ( GET_CODE ( ref ) != MEM ) return ; if ( ! MEM_VOLATILE_P ( ref ) && ! MEM_IN_STRUCT_P ( ref ) && ! MEM_SCALAR_P ( ref ) && ! MEM_NOTRAP_P ( ref ) && ! MEM_READONLY_P ( ref ) ) return ; if ( INSN_P ( insn ) ) base_ptr = & PATTERN ( insn ) ; else base_ptr = & insn ; for_each_rtx ( base_ptr , alpha_set_memflags_1 , ( void * ) ref ) ; } </s>

Given INSN , which is an INSN list or the PATTERN of a single insn generated to perform a memory operation , look for any MEMs in either a SET_DEST or a SET_SRC and copy the in-struct , unchanging , and volatile flags from REF into each of the MEMs found . If REF is not a MEM , do n't do anything .


<s> static int alpha_set_memflags_1 ( rtx * xp , void * data ) { rtx x = * xp , orig = ( rtx ) data ; if ( GET_CODE ( x ) != MEM ) return 0 ; MEM_VOLATILE_P ( x ) = MEM_VOLATILE_P ( orig ) ; MEM_IN_STRUCT_P ( x ) = MEM_IN_STRUCT_P ( orig ) ; MEM_SCALAR_P ( x ) = MEM_SCALAR_P ( orig ) ; MEM_NOTRAP_P ( x ) = MEM_NOTRAP_P ( orig ) ; MEM_READONLY_P ( x ) = MEM_READONLY_P ( orig ) ; return - 1 ; } </s>

Subfunction of the following function . Update the flags of any MEM found in part of X .


<s> void alpha_split_atomic_op ( enum rtx_code code , rtx mem , rtx val , rtx before , rtx after , rtx scratch ) { enum machine_mode mode = GET_MODE ( mem ) ; rtx label , x , cond = gen_rtx_REG ( DImode , REGNO ( scratch ) ) ; emit_insn ( gen_memory_barrier ( ) ) ; label = gen_label_rtx ( ) ; emit_label ( label ) ; label = gen_rtx_LABEL_REF ( DImode , label ) ; if ( before == NULL ) before = scratch ; emit_load_locked ( mode , before , mem ) ; if ( code == NOT ) x = gen_rtx_AND ( mode , gen_rtx_NOT ( mode , before ) , val ) ; else x = gen_rtx_fmt_ee ( code , mode , before , val ) ; if ( after ) emit_insn ( gen_rtx_SET ( VOIDmode , after , copy_rtx ( x ) ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , scratch , x ) ) ; emit_store_conditional ( mode , cond , mem , scratch ) ; x = gen_rtx_EQ ( DImode , cond , const0_rtx ) ; emit_unlikely_jump ( x , label ) ; emit_insn ( gen_memory_barrier ( ) ) ; } </s>

Expand an an atomic fetch-and-operate pattern . CODE is the binary operation to perform . MEM is the memory on which to operate . VAL is the second operand of the binary operator . BEFORE and AFTER are optional locations to return the value of MEM either before of after the operation . SCRATCH is a scratch register .


<s> void alpha_split_compare_and_swap ( rtx retval , rtx mem , rtx oldval , rtx newval , rtx scratch ) { enum machine_mode mode = GET_MODE ( mem ) ; rtx label1 , label2 , x , cond = gen_lowpart ( DImode , scratch ) ; emit_insn ( gen_memory_barrier ( ) ) ; label1 = gen_rtx_LABEL_REF ( DImode , gen_label_rtx ( ) ) ; label2 = gen_rtx_LABEL_REF ( DImode , gen_label_rtx ( ) ) ; emit_label ( XEXP ( label1 , 0 ) ) ; emit_load_locked ( mode , retval , mem ) ; x = gen_lowpart ( DImode , retval ) ; if ( oldval == const0_rtx ) x = gen_rtx_NE ( DImode , x , const0_rtx ) ; else { x = gen_rtx_EQ ( DImode , x , oldval ) ; emit_insn ( gen_rtx_SET ( VOIDmode , cond , x ) ) ; x = gen_rtx_EQ ( DImode , cond , const0_rtx ) ; } emit_unlikely_jump ( x , label2 ) ; emit_move_insn ( scratch , newval ) ; emit_store_conditional ( mode , cond , mem , scratch ) ; x = gen_rtx_EQ ( DImode , cond , const0_rtx ) ; emit_unlikely_jump ( x , label1 ) ; emit_insn ( gen_memory_barrier ( ) ) ; emit_label ( XEXP ( label2 , 0 ) ) ; } </s>


<s> static bool alpha_split_complex_arg ( tree type ) { return TYPE_MODE ( type ) != TCmode ; } </s>

TCmode complex values are passed by invisible reference . We should not split these values .


<s> int alpha_split_conditional_move ( enum rtx_code code , rtx dest , rtx cond , rtx t_rtx , rtx f_rtx ) { HOST_WIDE_INT t , f , diff ; enum machine_mode mode ; rtx target , subtarget , tmp ; mode = GET_MODE ( dest ) ; t = INTVAL ( t_rtx ) ; f = INTVAL ( f_rtx ) ; diff = t - f ; if ( ( ( code == NE || code == EQ ) && diff < 0 ) || ( code == GE || code == GT ) ) { code = reverse_condition ( code ) ; diff = t , t = f , f = diff ; diff = t - f ; } subtarget = target = dest ; if ( mode != DImode ) { target = gen_lowpart ( DImode , dest ) ; if ( ! no_new_pseudos ) subtarget = gen_reg_rtx ( DImode ) ; else subtarget = target ; } if ( f == 0 && exact_log2 ( diff ) > 0 && ( diff <= 8 || alpha_tune == PROCESSOR_EV6 ) ) { tmp = gen_rtx_fmt_ee ( code , DImode , cond , const0_rtx ) ; emit_insn ( gen_rtx_SET ( VOIDmode , copy_rtx ( subtarget ) , tmp ) ) ; tmp = gen_rtx_ASHIFT ( DImode , copy_rtx ( subtarget ) , GEN_INT ( exact_log2 ( t ) ) ) ; emit_insn ( gen_rtx_SET ( VOIDmode , target , tmp ) ) ; } else if ( f == 0 && t == - 1 ) { tmp = gen_rtx_fmt_ee ( code , DImode , cond , const0_rtx ) ; emit_insn ( gen_rtx_SET ( VOIDmode , copy_rtx ( subtarget ) , tmp ) ) ; emit_insn ( gen_negdi2 ( target , copy_rtx ( subtarget ) ) ) ; } else if ( diff == 1 || diff == 4 || diff == 8 ) { rtx add_op ; tmp = gen_rtx_fmt_ee ( code , DImode , cond , const0_rtx ) ; emit_insn ( gen_rtx_SET ( VOIDmode , copy_rtx ( subtarget ) , tmp ) ) ; if ( diff == 1 ) emit_insn ( gen_adddi3 ( target , copy_rtx ( subtarget ) , GEN_INT ( f ) ) ) ; else { add_op = GEN_INT ( f ) ; if ( sext_add_operand ( add_op , mode ) ) { tmp = gen_rtx_MULT ( DImode , copy_rtx ( subtarget ) , GEN_INT ( diff ) ) ; tmp = gen_rtx_PLUS ( DImode , tmp , add_op ) ; emit_insn ( gen_rtx_SET ( VOIDmode , target , tmp ) ) ; } else return 0 ; } } else return 0 ; return 1 ; } </s>

Simplify a conditional move of two constants into a setcc with arithmetic . This is done with a splitter since combine would just undo the work if done during code generation . It also catches cases we would n't have before cse .


<s> bool alpha_split_const_mov ( enum machine_mode mode , rtx * operands ) { HOST_WIDE_INT i0 , i1 ; rtx temp = NULL_RTX ; alpha_extract_integer ( operands [ 1 ] , & i0 , & i1 ) ; if ( HOST_BITS_PER_WIDE_INT >= 64 || i1 == - ( i0 < 0 ) ) temp = alpha_emit_set_const ( operands [ 0 ] , mode , i0 , 3 , false ) ; if ( ! temp && TARGET_BUILD_CONSTANTS ) temp = alpha_emit_set_long_const ( operands [ 0 ] , i0 , i1 ) ; if ( temp ) { if ( ! rtx_equal_p ( operands [ 0 ] , temp ) ) emit_move_insn ( operands [ 0 ] , temp ) ; return true ; } return false ; } </s>

Operand 1 is known to be a constant , and should require more than one instruction to load . Emit that multi-part load .


<s> void alpha_split_lock_test_and_set ( rtx retval , rtx mem , rtx val , rtx scratch ) { enum machine_mode mode = GET_MODE ( mem ) ; rtx label , x , cond = gen_lowpart ( DImode , scratch ) ; emit_insn ( gen_memory_barrier ( ) ) ; label = gen_rtx_LABEL_REF ( DImode , gen_label_rtx ( ) ) ; emit_label ( XEXP ( label , 0 ) ) ; emit_load_locked ( mode , retval , mem ) ; emit_move_insn ( scratch , val ) ; emit_store_conditional ( mode , cond , mem , scratch ) ; x = gen_rtx_EQ ( DImode , cond , const0_rtx ) ; emit_unlikely_jump ( x , label ) ; } </s>


<s> void alpha_split_tfmode_frobsign ( rtx operands [ 3 ] , rtx ( * operation ) ( rtx , rtx , rtx ) ) { rtx high_bit = operands [ 2 ] ; rtx scratch ; int move ; alpha_split_tfmode_pair ( operands ) ; move = 1 ; if ( rtx_equal_p ( operands [ 0 ] , operands [ 2 ] ) ) move = 0 ; else if ( rtx_equal_p ( operands [ 1 ] , operands [ 2 ] ) ) { if ( rtx_equal_p ( operands [ 0 ] , high_bit ) ) move = 2 ; else move = - 1 ; } if ( move < 0 ) emit_move_insn ( operands [ 0 ] , operands [ 2 ] ) ; scratch = operands [ move < 2 ? 1 : 3 ] ; emit_insn ( ( * operation ) ( scratch , high_bit , operands [ 3 ] ) ) ; if ( move > 0 ) { emit_move_insn ( operands [ 0 ] , operands [ 2 ] ) ; if ( move > 1 ) emit_move_insn ( operands [ 1 ] , scratch ) ; } } </s>

Implement negtf2 or abstf2 . Op0 is destination , op1 is source , op2 is a register containing the sign bit , operation is the logical operation to be performed .


<s> void alpha_split_tfmode_pair ( rtx operands [ 4 ] ) { switch ( GET_CODE ( operands [ 1 ] ) ) { case REG : operands [ 3 ] = gen_rtx_REG ( DImode , REGNO ( operands [ 1 ] ) + 1 ) ; operands [ 2 ] = gen_rtx_REG ( DImode , REGNO ( operands [ 1 ] ) ) ; break ; case MEM : operands [ 3 ] = adjust_address ( operands [ 1 ] , DImode , 8 ) ; operands [ 2 ] = adjust_address ( operands [ 1 ] , DImode , 0 ) ; break ; case CONST_DOUBLE : gcc_assert ( operands [ 1 ] == CONST0_RTX ( TFmode ) ) ; operands [ 2 ] = operands [ 3 ] = const0_rtx ; break ; default : gcc_unreachable ( ) ; } switch ( GET_CODE ( operands [ 0 ] ) ) { case REG : operands [ 1 ] = gen_rtx_REG ( DImode , REGNO ( operands [ 0 ] ) + 1 ) ; operands [ 0 ] = gen_rtx_REG ( DImode , REGNO ( operands [ 0 ] ) ) ; break ; case MEM : operands [ 1 ] = adjust_address ( operands [ 0 ] , DImode , 8 ) ; operands [ 0 ] = adjust_address ( operands [ 0 ] , DImode , 0 ) ; break ; default : gcc_unreachable ( ) ; } } </s>

Split a TFmode OP [ 1 ] into DImode OP [ 2,3 ] and likewise for OP [ 0 ] into OP [ 0,1 ] . Naturally , output operand ordering is little-endian .


<s> rtx alpha_tablejump_addr_vec ( rtx insn ) { rtx tmp ; tmp = JUMP_LABEL ( insn ) ; if ( ! tmp ) return NULL_RTX ; tmp = NEXT_INSN ( tmp ) ; if ( ! tmp ) return NULL_RTX ; if ( GET_CODE ( tmp ) == JUMP_INSN && GET_CODE ( PATTERN ( tmp ) ) == ADDR_DIFF_VEC ) return PATTERN ( tmp ) ; return NULL_RTX ; } </s>

Return the ADDR_VEC associated with a tablejump insn .


<s> rtx alpha_tablejump_best_label ( rtx insn ) { rtx jump_table = alpha_tablejump_addr_vec ( insn ) ; rtx best_label = NULL_RTX ; if ( jump_table ) { int n_labels = XVECLEN ( jump_table , 1 ) ; int best_count = - 1 ; int i , j ; for ( i = 0 ; i < n_labels ; i ++ ) { int count = 1 ; for ( j = i + 1 ; j < n_labels ; j ++ ) if ( XEXP ( XVECEXP ( jump_table , 1 , i ) , 0 ) == XEXP ( XVECEXP ( jump_table , 1 , j ) , 0 ) ) count ++ ; if ( count > best_count ) best_count = count , best_label = XVECEXP ( jump_table , 1 , i ) ; } } return best_label ? best_label : const0_rtx ; } </s>

Return the label of the predicted edge , or CONST0_RTX if we do n't know .


<s> rtx alpha_use_linkage ( rtx linkage ATTRIBUTE_UNUSED , tree cfundecl ATTRIBUTE_UNUSED , int lflag ATTRIBUTE_UNUSED , int rflag ATTRIBUTE_UNUSED ) { return NULL_RTX ; } </s>

Return a SYMBOL_REF representing the reference to the .linkage entry of function FUNC built for calls made from CFUNDECL . LFLAG is 1 if this is the reference to the linkage pointer value , 0 if this is the reference to the function entry value . RFLAG is 1 if this a reduced reference ( code address only ) , 0 if this is a full reference .


<s> static bool alpha_vector_mode_supported_p ( enum machine_mode mode ) { return mode == V8QImode || mode == V4HImode || mode == V2SImode ; } </s>

Alpha implements a couple of integer vector mode operations when TARGET_MAX is enabled . We do not check TARGET_MAX here , however , which allows the vectorizer to operate on e.g . move instructions , or when expand_vector_operations can do something useful .


<s> static bool decl_has_samegp ( tree decl ) { if ( ! ( * targetm . binds_local_p ) ( decl ) ) return false ; if ( TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA ) return true ; return ! TREE_PUBLIC ( decl ) || ! DECL_EXTERNAL ( decl ) ; } </s>

Return true if the function DECL will share the same GP as any function in the current unit of translation .


<s> int direct_return ( void ) { return ( ! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK && reload_completed && alpha_sa_size ( ) == 0 && get_frame_size ( ) == 0 && current_function_outgoing_args_size == 0 && current_function_pretend_args_size == 0 ) ; } </s>

Return non-zero if this function is known to have a null epilogue .


<s> static void emit_frame_store_1 ( rtx value , rtx base_reg , HOST_WIDE_INT frame_bias , HOST_WIDE_INT base_ofs , rtx frame_reg ) { rtx addr , mem , insn ; addr = plus_constant ( base_reg , base_ofs ) ; mem = gen_rtx_MEM ( DImode , addr ) ; set_mem_alias_set ( mem , alpha_sr_alias_set ) ; insn = emit_move_insn ( mem , value ) ; RTX_FRAME_RELATED_P ( insn ) = 1 ; if ( frame_bias || value != frame_reg ) { if ( frame_bias ) { addr = plus_constant ( stack_pointer_rtx , frame_bias + base_ofs ) ; mem = gen_rtx_MEM ( DImode , addr ) ; } REG_NOTES ( insn ) = gen_rtx_EXPR_LIST ( REG_FRAME_RELATED_EXPR , gen_rtx_SET ( VOIDmode , mem , frame_reg ) , REG_NOTES ( insn ) ) ; } } </s>

Generates a store with the proper unwind info attached . VALUE is stored at BASE_REG+BASE_OFS . If FRAME_BIAS is nonzero , then BASE_REG contains SP+FRAME_BIAS , and that is the unwind info that should be generated . If FRAME_REG ! = VALUE , then VALUE is being stored on behalf of FRAME_REG , and FRAME_REG should be present in the unwind .


<s> static rtx emit_insxl ( enum machine_mode mode , rtx op1 , rtx op2 ) { rtx ret = gen_reg_rtx ( DImode ) ; rtx ( * fn ) ( rtx , rtx , rtx ) ; if ( WORDS_BIG_ENDIAN ) { if ( mode == QImode ) fn = gen_insbl_be ; else fn = gen_inswl_be ; } else { if ( mode == QImode ) fn = gen_insbl_le ; else fn = gen_inswl_le ; } emit_insn ( fn ( ret , op1 , op2 ) ) ; return ret ; } </s>

A subroutine of the atomic operation splitters . Emit an insxl instruction in MODE .


<s> static void emit_load_locked ( enum machine_mode mode , rtx reg , rtx mem ) { rtx ( * fn ) ( rtx , rtx ) = NULL ; if ( mode == SImode ) fn = gen_load_locked_si ; else if ( mode == DImode ) fn = gen_load_locked_di ; emit_insn ( fn ( reg , mem ) ) ; } </s>

A subroutine of the atomic operation splitters . Emit a load-locked instruction in MODE . For QI/HImode , possibly use a pattern than includes the zero_extend operation .


<s> static void emit_store_conditional ( enum machine_mode mode , rtx res , rtx mem , rtx val ) { rtx ( * fn ) ( rtx , rtx , rtx ) = NULL ; if ( mode == SImode ) fn = gen_store_conditional_si ; else if ( mode == DImode ) fn = gen_store_conditional_di ; emit_insn ( fn ( res , mem , val ) ) ; } </s>

A subroutine of the atomic operation splitters . Emit a store-conditional instruction in MODE .


<s> static void emit_unlikely_jump ( rtx cond , rtx label ) { rtx very_unlikely = GEN_INT ( REG_BR_PROB_BASE / 100 - 1 ) ; rtx x ; x = gen_rtx_IF_THEN_ELSE ( VOIDmode , cond , label , pc_rtx ) ; x = emit_jump_insn ( gen_rtx_SET ( VOIDmode , pc_rtx , x ) ) ; REG_NOTES ( x ) = gen_rtx_EXPR_LIST ( REG_BR_PROB , very_unlikely , NULL_RTX ) ; } </s>

Mark the previous jump instruction as unlikely .


<s> rtx function_arg ( CUMULATIVE_ARGS cum , enum machine_mode mode , tree type , int named ATTRIBUTE_UNUSED ) { int basereg ; int num_args ; if ( type && AGGREGATE_TYPE_P ( type ) ) basereg = 16 ; else { gcc_assert ( ! COMPLEX_MODE_P ( mode ) ) ; if ( TARGET_FPREGS && GET_MODE_CLASS ( mode ) == MODE_FLOAT ) basereg = 32 + 16 ; else basereg = 16 ; } { if ( mode == VOIDmode ) return alpha_arg_info_reg_val ( cum ) ; num_args = cum . num_args ; if ( num_args >= 6 || targetm . calls . must_pass_in_stack ( mode , type ) ) return NULL_RTX ; } { int size ; if ( mode == VOIDmode ) { int i ; HOST_WIDE_INT lo ; HOST_WIDE_INT hi ; rtx ciw ; lo = 0 ; for ( i = 0 ; i < cum . num_reg_words && i < 5 ; i ++ ) if ( cum . reg_args_type [ i ] ) lo |= ( 1 << ( 7 - i ) ) ; if ( cum . num_reg_words == 6 && cum . reg_args_type [ 5 ] ) lo |= 7 ; else lo |= cum . num_reg_words ; hi = ( cum . num_args << 20 ) | cum . num_arg_words ; lo = lo | ( ( HOST_WIDE_INT ) cum . num_args << 52 ) | ( ( HOST_WIDE_INT ) cum . num_arg_words << 32 ) ; hi = 0 ; ciw = immed_double_const ( lo , hi , DImode ) ; return gen_rtx_UNSPEC ( DImode , gen_rtvec ( 1 , ciw ) , UNSPEC_UMK_LOAD_CIW ) ; } size = ALPHA_ARG_SIZE ( mode , type , named ) ; num_args = cum . num_reg_words ; if ( cum . force_stack || cum . num_reg_words + size > 6 || targetm . calls . must_pass_in_stack ( mode , type ) ) return NULL_RTX ; else if ( type && TYPE_MODE ( type ) == BLKmode ) { rtx reg1 , reg2 ; reg1 = gen_rtx_REG ( DImode , num_args + 16 ) ; reg1 = gen_rtx_EXPR_LIST ( DImode , reg1 , const0_rtx ) ; if ( size == 0 ) return NULL_RTX ; else if ( size == 1 ) return gen_rtx_PARALLEL ( mode , gen_rtvec ( 1 , reg1 ) ) ; else { reg2 = gen_rtx_REG ( DImode , num_args + 17 ) ; reg2 = gen_rtx_EXPR_LIST ( DImode , reg2 , GEN_INT ( 8 ) ) ; return gen_rtx_PARALLEL ( mode , gen_rtvec ( 2 , reg1 , reg2 ) ) ; } } } { if ( cum >= 6 ) return NULL_RTX ; num_args = cum ; if ( type == void_type_node ) basereg = 16 ; else if ( targetm . calls . must_pass_in_stack ( mode , type ) ) return NULL_RTX ; } return gen_rtx_REG ( mode , num_args + basereg ) ; } </s>

Return an RTL expression containing the register for the given mode , or 0 if the argument is to be passed on the stack . INCOMING_P is nonzero if this is an incoming argument to the current function .


<s> rtx function_value ( tree valtype , tree func ATTRIBUTE_UNUSED , enum machine_mode mode ) { unsigned int regnum , dummy ; enum mode_class class ; gcc_assert ( ! valtype || ! alpha_return_in_memory ( valtype , func ) ) ; if ( valtype ) mode = TYPE_MODE ( valtype ) ; class = GET_MODE_CLASS ( mode ) ; switch ( class ) { case MODE_INT : PROMOTE_MODE ( mode , dummy , valtype ) ; case MODE_COMPLEX_INT : case MODE_VECTOR_INT : regnum = 0 ; break ; case MODE_FLOAT : regnum = 32 ; break ; case MODE_COMPLEX_FLOAT : { enum machine_mode cmode = GET_MODE_INNER ( mode ) ; return gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , gen_rtx_EXPR_LIST ( VOIDmode , gen_rtx_REG ( cmode , 32 ) , const0_rtx ) , gen_rtx_EXPR_LIST ( VOIDmode , gen_rtx_REG ( cmode , 33 ) , GEN_INT ( GET_MODE_SIZE ( cmode ) ) ) ) ) ; } default : gcc_unreachable ( ) ; } return gen_rtx_REG ( mode , regnum ) ; } </s>

Handle FUNCTION_VALUE , FUNCTION_OUTGOING_VALUE , and LIBCALL_VALUE macros . For v9 , function return values are subject to the same rules as arguments , except that up to 32 bytes may be returned in registers .


<s> void get_aligned_mem ( rtx ref , rtx * paligned_mem , rtx * pbitnum ) { rtx base ; HOST_WIDE_INT disp , offset ; gcc_assert ( GET_CODE ( ref ) == MEM ) ; if ( reload_in_progress && ! memory_address_p ( GET_MODE ( ref ) , XEXP ( ref , 0 ) ) ) { base = find_replacement ( & XEXP ( ref , 0 ) ) ; gcc_assert ( memory_address_p ( GET_MODE ( ref ) , base ) ) ; } else base = XEXP ( ref , 0 ) ; if ( GET_CODE ( base ) == PLUS ) disp = INTVAL ( XEXP ( base , 1 ) ) , base = XEXP ( base , 0 ) ; else disp = 0 ; if ( MEM_ALIGN ( ref ) >= 32 ) offset = 0 ; else offset = disp & 3 ; * paligned_mem = widen_memory_access ( ref , SImode , - offset ) ; if ( WORDS_BIG_ENDIAN ) offset = 32 - ( GET_MODE_BITSIZE ( GET_MODE ( ref ) ) + offset * 8 ) ; else offset *= 8 ; * pbitnum = GEN_INT ( offset ) ; } </s>

REF is an alignable memory location . Place an aligned SImode reference into * PALIGNED_MEM and the number of bits to shift into * PBITNUM . SCRATCH is a free register for use in reloading out of range stack slots .


<s> static const char * get_some_local_dynamic_name ( void ) { rtx insn ; if ( cfun -> machine -> some_ld_name ) return cfun -> machine -> some_ld_name ; for ( insn = get_insns ( ) ; insn ; insn = NEXT_INSN ( insn ) ) if ( INSN_P ( insn ) && for_each_rtx ( & PATTERN ( insn ) , get_some_local_dynamic_name_1 , 0 ) ) return cfun -> machine -> some_ld_name ; gcc_unreachable ( ) ; } </s>

Locate some local-dynamic symbol still in use by this function so that we can print its name in local-dynamic base patterns .


<s> static int get_some_local_dynamic_name_1 ( rtx * px , void * data ATTRIBUTE_UNUSED ) { rtx x = * px ; if ( GET_CODE ( x ) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL ( x ) == TLS_MODEL_LOCAL_DYNAMIC ) { cfun -> machine -> some_ld_name = XSTR ( x , 0 ) ; return 1 ; } return 0 ; } </s>


<s> rtx get_unaligned_address ( rtx ref , int extra_offset ) { rtx base ; HOST_WIDE_INT offset = 0 ; gcc_assert ( GET_CODE ( ref ) == MEM ) ; if ( reload_in_progress && ! memory_address_p ( GET_MODE ( ref ) , XEXP ( ref , 0 ) ) ) { base = find_replacement ( & XEXP ( ref , 0 ) ) ; gcc_assert ( memory_address_p ( GET_MODE ( ref ) , base ) ) ; } else base = XEXP ( ref , 0 ) ; if ( GET_CODE ( base ) == PLUS ) offset += INTVAL ( XEXP ( base , 1 ) ) , base = XEXP ( base , 0 ) ; return plus_constant ( base , offset + extra_offset ) ; } </s>

Similar , but just get the address . Handle the two reload cases . Add EXTRA_OFFSET to the address we return .


<s>
void
print_operand_address
(
FILE
*
file
,
rtx
addr
)
{
int
basereg
=
31
;
HOST_WIDE_INT
offset
=
0
;
if
(
GET_CODE
(
addr
)
==
AND
)
addr
=
XEXP
(
addr
,
0
)
;
if
(
GET_CODE
(
addr
)
==
PLUS
&&
GET_CODE
(
XEXP
(
addr
,
1
)
)
==
CONST_INT
)
{
offset
=
INTVAL
(
XEXP
(
addr
,
1
)
)
;
addr
=
XEXP
(
addr
,
0
)
;
}
if
(
GET_CODE
(
addr
)
==
LO_SUM
)
{
const
char
*
reloc16
,
*
reloclo
;
rtx
op1
=
XEXP
(
addr
,
1
)
;
if
(
GET_CODE
(
op1
)
==
CONST
&&
GET_CODE
(
XEXP
(
op1
,
0
)
)
==
UNSPEC
)
{
op1
=
XEXP
(
op1
,
0
)
;
switch
(
XINT
(
op1
,
1
)
)
{
case
UNSPEC_DTPREL
:
reloc16
=
;
reloclo
=
(
alpha_tls_size
==
16
"dtprel"
:
"dtprello"
)
;
break
;
case
UNSPEC_TPREL
:
reloc16
=
;
reloclo
=
(
alpha_tls_size
==
16
"tprel"
:
"tprello"
)
;
break
;
default
:
output_operand_lossage
(
"unknown relocation unspec"
)
;
return
;
}
output_addr_const
(
file
,
XVECEXP
(
op1
,
0
,
0
)
)
;
}
else
{
reloc16
=
"gprel"
;
reloclo
=
"gprellow"
;
output_addr_const
(
file
,
op1
)
;
}
if
(
offset
)
fprintf
(
file
,
"+"
HOST_WIDE_INT_PRINT_DEC
,
offset
)
;
addr
=
XEXP
(
addr
,
0
)
;
switch
(
GET_CODE
(
addr
)
)
{
case
REG
:
basereg
=
REGNO
(
addr
)
;
break
;
case
SUBREG
:
basereg
=
subreg_regno
(
addr
)
;
break
;
default
:
gcc_unreachable
(
)
;
}
fprintf
(
file
,
"($%d)\t\t!%s"
,
basereg
,
(
basereg
==
29
reloc16
:
reloclo
)
)
;
return
;
}
switch
(
GET_CODE
(
addr
)
)
{
case
REG
:
basereg
=
REGNO
(
addr
)
;
break
;
case
SUBREG
:
basereg
=
subreg_regno
(
addr
)
;
break
;
case
CONST_INT
:
offset
=
INTVAL
(
addr
)
;
break
;
case
SYMBOL_REF
:
fprintf
(
file
,
"%s"
,
XSTR
(
addr
,
0
)
)
;
return
;
case
CONST
:
gcc_assert
(
GET_CODE
(
XEXP
(
addr
,
0
)
)
==
PLUS
&&
GET_CODE
(
XEXP
(
XEXP
(
addr
,
0
)
,
0
)
)
==
SYMBOL_REF
)
;
fprintf
(
file
,
"%s+"
HOST_WIDE_INT_PRINT_DEC
,
XSTR
(
XEXP
(
XEXP
(
addr
,
0
)
,
0
)
,
0
)
,
INTVAL
(
XEXP
(
XEXP
(
addr
,
0
)
,
1
)
)
)
;
return
;
default
:
gcc_unreachable
(
)
;
}
fprintf
(
file
,
HOST_WIDE_INT_PRINT_DEC
"($%d)"
,
offset
,
basereg
)
;
}
</s>

Print the operand address represented by the rtx addr


<s> rtx resolve_reload_operand ( rtx op ) { if ( reload_in_progress ) { rtx tmp = op ; if ( GET_CODE ( tmp ) == SUBREG ) tmp = SUBREG_REG ( tmp ) ; if ( GET_CODE ( tmp ) == REG && REGNO ( tmp ) >= FIRST_PSEUDO_REGISTER ) { op = reg_equiv_memory_loc [ REGNO ( tmp ) ] ; if ( op == 0 ) return 0 ; } } return op ; } </s>

Used by aligned_memory_operand and unaligned_memory_operand to resolve what reload is going to do with OP if it 's a register .


<s> enum reg_class secondary_reload_class ( enum reg_class class , enum machine_mode mode , rtx x , int in ) { if ( ( mode == QImode || mode == HImode ) && ! TARGET_BWX ) { if ( GET_CODE ( x ) == MEM || ( GET_CODE ( x ) == REG && REGNO ( x ) >= FIRST_PSEUDO_REGISTER ) || ( GET_CODE ( x ) == SUBREG && ( GET_CODE ( SUBREG_REG ( x ) ) == MEM || ( GET_CODE ( SUBREG_REG ( x ) ) == REG && REGNO ( SUBREG_REG ( x ) ) >= FIRST_PSEUDO_REGISTER ) ) ) ) { if ( ! in || ! aligned_memory_operand ( x , mode ) ) return GENERAL_REGS ; } } if ( class == FLOAT_REGS ) { if ( GET_CODE ( x ) == MEM && GET_CODE ( XEXP ( x , 0 ) ) == AND ) return GENERAL_REGS ; if ( GET_CODE ( x ) == SUBREG && ( GET_MODE_SIZE ( GET_MODE ( x ) ) > GET_MODE_SIZE ( GET_MODE ( SUBREG_REG ( x ) ) ) ) ) return GENERAL_REGS ; if ( in && INTEGRAL_MODE_P ( mode ) && ! ( memory_operand ( x , mode ) || x == const0_rtx ) ) return GENERAL_REGS ; } </s>

Return the class of any secondary reload register that is needed to move IN into a register in class CLASS using mode MODE . Profiling has showed this routine and its descendants account for a significant amount of compile time ( ~7 % ) . So it has been optimized to reduce redundant computations and eliminate useless function calls . It might be worthwhile to try and make this a leaf function too .


<s> static rtx set_frame_related_p ( void ) { rtx seq = get_insns ( ) ; rtx insn ; end_sequence ( ) ; if ( ! seq ) return NULL_RTX ; if ( INSN_P ( seq ) ) { insn = seq ; while ( insn != NULL_RTX ) { RTX_FRAME_RELATED_P ( insn ) = 1 ; insn = NEXT_INSN ( insn ) ; } seq = emit_insn ( seq ) ; } else { seq = emit_insn ( seq ) ; RTX_FRAME_RELATED_P ( seq ) = 1 ; } return seq ; } </s>

Helper function to set RTX_FRAME_RELATED_P on instructions , including sequences .


<s> static enum tls_model tls_symbolic_operand_type ( rtx symbol ) { enum tls_model model ; if ( GET_CODE ( symbol ) != SYMBOL_REF ) return 0 ; model = SYMBOL_REF_TLS_MODEL ( symbol ) ; if ( model == TLS_MODEL_LOCAL_EXEC && alpha_tls_size == 64 ) model = TLS_MODEL_INITIAL_EXEC ; return model ; } </s>

Return the TLS model to use for SYMBOL .


<s> rtx unicosmk_add_call_info_word ( rtx x ATTRIBUTE_UNUSED ) { return NULL_RTX ; } </s>

Add a call information word ( CIW ) to the list of the current function 's CIWs and return its index . X is a CONST_INT or CONST_DOUBLE representing the CIW .


<s> void unicosmk_add_extern ( const char * name ) { struct unicosmk_extern_list * p ; p = ( struct unicosmk_extern_list * ) xmalloc ( sizeof ( struct unicosmk_extern_list ) ) ; p -> next = unicosmk_extern_head ; p -> name = name ; unicosmk_extern_head = p ; } </s>


<s> static void unicosmk_asm_named_section ( const char * name , unsigned int flags , tree decl ATTRIBUTE_UNUSED ) { const char * kind ; fputs ( "\t.endp\n\n" , asm_out_file ) ; if ( flags & SECTION_MAIN ) fputs ( "\t.start\tmain\n" , asm_out_file ) ; if ( flags & SECTION_CODE ) kind = "code" ; else if ( flags & SECTION_PUBLIC ) kind = "common" ; else kind = "data" ; if ( current_section_align != 0 ) fprintf ( asm_out_file , "\t.psect\t%s,%d,%s\n" , name , current_section_align , kind ) ; else fprintf ( asm_out_file , "\t.psect\t%s,%s\n" , name , kind ) ; } </s>

Switch to an arbitrary section NAME with attributes as specified by FLAGS . ALIGN specifies any known alignment requirements for the section ; 0 if the default should be used .


<s> void unicosmk_defer_case_vector ( rtx lab , rtx vec ) { struct machine_function * machine = cfun -> machine ; vec = gen_rtx_EXPR_LIST ( VOIDmode , lab , vec ) ; machine -> addr_list = gen_rtx_EXPR_LIST ( VOIDmode , vec , machine -> addr_list ) ; } </s>

Add a case vector to the current function 's list of deferred case vectors . Case vectors have to be put into a separate section because CAM does not allow data definitions in code sections .


<s> static void unicosmk_file_end ( void ) { fputs ( "\t.endp\n\n" , asm_out_file ) ; unicosmk_output_externs ( asm_out_file ) ; unicosmk_output_dex ( asm_out_file ) ; fputs ( "\t.end\t" , asm_out_file ) ; unicosmk_output_module_name ( asm_out_file ) ; putc ( '\n' , asm_out_file ) ; } </s>

Output text to appear at the end of an assembler file . This includes all pending extern declarations and DEX expressions .


"\t.repeat (gcc@n@bytes - gcc@here) / 4\n"

Output text that to appear at the beginning of an assembler file .


<s> static void unicosmk_gen_dsib ( unsigned long * imaskP ATTRIBUTE_UNUSED ) { } </s>

Set up the dynamic subprogram information block ( DSIB ) and update the frame pointer register ( $ 15 ) for subroutines which have a frame . If the subroutine does n't have a frame , simply increment $ 15 .


<s> int unicosmk_initial_elimination_offset ( int from , int to ) { int fixed_size ; fixed_size = alpha_sa_size ( ) ; if ( fixed_size != 0 ) fixed_size += 48 ; if ( from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) return - fixed_size ; else if ( from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM ) return 0 ; else if ( from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM ) return ( ALPHA_ROUND ( current_function_outgoing_args_size ) + ALPHA_ROUND ( get_frame_size ( ) ) ) ; else if ( from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM ) return ( ALPHA_ROUND ( fixed_size ) + ALPHA_ROUND ( get_frame_size ( ) + current_function_outgoing_args_size ) ) ; else gcc_unreachable ( ) ; } </s>

Define the offset between two registers , one to be eliminated , and the other its replacement , at the start of a routine .


<s> static bool unicosmk_must_pass_in_stack ( enum machine_mode mode , tree type ) { if ( type == NULL ) return false ; if ( TREE_CODE ( TYPE_SIZE ( type ) ) != INTEGER_CST ) return true ; if ( TREE_ADDRESSABLE ( type ) ) return true ; return ALPHA_ARG_SIZE ( mode , type , 0 ) > 2 ; } </s>

This evaluates to true if we do not know how to pass TYPE solely in registers . This is the case for all arguments that do not fit in two registers .


<s> static int unicosmk_need_dex ( rtx x ATTRIBUTE_UNUSED ) { return 0 ; } </s>

Return the DEX number if X must be replaced by a DEX expression and 0 otherwise .


<s> static void unicosmk_output_addr_vec ( FILE * file , rtx vec ) { rtx lab = XEXP ( vec , 0 ) ; rtx body = XEXP ( vec , 1 ) ; int vlen = XVECLEN ( body , 0 ) ; int idx ; ( * targetm . asm_out . internal_label ) ( file , "L" , CODE_LABEL_NUMBER ( lab ) ) ; for ( idx = 0 ; idx < vlen ; idx ++ ) { ASM_OUTPUT_ADDR_VEC_ELT ( file , CODE_LABEL_NUMBER ( XEXP ( XVECEXP ( body , 0 , idx ) , 0 ) ) ) ; } } </s>


<s> void unicosmk_output_align ( FILE * file , int align ) { if ( inside_function ) fprintf ( file , "\tgcc@code@align\t%d\n" , align ) ; else fprintf ( file , "\t.align\t%d\n" , align ) ; } </s>

Output an alignment directive . We have to use the macro 'gcc @ code @ align ' in code sections because .align fill unused space with zeroes .


<s>
void
unicosmk_output_common
(
FILE
*
file
,
const
char
*
name
,
int
size
,
int
align
)
{
tree
name_tree
;
printf
(
"T3E__: common %s\n"
,
name
)
;
common_section
(
)
;
fputs
(
"\t.endp\n\n\t.psect "
,
file
)
;
assemble_name
(
file
,
name
)
;
fprintf
(
file
,
",%d,common\n"
,
floor_log2
(
align
/
BITS_PER_UNIT
)
)
;
fprintf
(
file
,
"\t.byte\t0:%d\n"
,
size
)
;
name_tree
=
get_identifier
(
name
)
;
TREE_ASM_WRITTEN
(
name_tree
)
=
1
;
}
</s>

Output the definition of a common variable .

alpha
"T3E__: common %s\n"
"\t.endp\n\n\t.psect "
",%d,common\n"
"\t.byte\t0:%d\n"
1


<s> static void unicosmk_output_default_externs ( FILE * file ) { static const char * const externs [ ] = { "__T3E_MISMATCH" } ; int i ; int n ; n = ARRAY_SIZE ( externs ) ; for ( i = 0 ; i < n ; i ++ ) fprintf ( file , "\t.extern\t%s\n" , externs [ i ] ) ; } </s>

Output extern declarations which are required for every asm file .


<s> static void unicosmk_output_deferred_case_vectors ( FILE * file ) { struct machine_function * machine = cfun -> machine ; rtx t ; if ( machine -> addr_list == NULL_RTX ) return ; data_section ( ) ; for ( t = machine -> addr_list ; t ; t = XEXP ( t , 1 ) ) unicosmk_output_addr_vec ( file , XEXP ( t , 0 ) ) ; } </s>

Output current function 's deferred case vectors .


<s>
static
void
unicosmk_output_dex
(
FILE
*
file
)
{
struct
unicosmk_dex
*
dex
;
int
i
;
if
(
unicosmk_dex_list
==
)
return
;
fprintf
(
file
,
"\t.dexstart\n"
)
;
i
=
unicosmk_dex_count
;
for
(
dex
=
unicosmk_dex_list
;
dex
;
dex
=
dex
->
next
)
{
fprintf
(
file
,
"\tDEX (%d) = "
,
i
)
;
assemble_name
(
file
,
dex
->
name
)
;
putc
(
'\n'
,
file
)
;
i
;
}
fprintf
(
file
,
"\t.dexend\n"
)
;
}
</s>

Output the DEX definitions for this file .


<s> static void unicosmk_output_externs ( FILE * file ) { struct unicosmk_extern_list * p ; const char * real_name ; int len ; tree name_tree ; len = strlen ( user_label_prefix ) ; for ( p = unicosmk_extern_head ; p != 0 ; p = p -> next ) { real_name = default_strip_name_encoding ( p -> name ) ; if ( len && p -> name [ 0 ] == '*' && ! memcmp ( real_name , user_label_prefix , len ) ) real_name += len ; name_tree = get_identifier ( real_name ) ; if ( ! TREE_ASM_WRITTEN ( name_tree ) ) { TREE_ASM_WRITTEN ( name_tree ) = 1 ; fputs ( "\t.extern\t" , file ) ; assemble_name ( file , p -> name ) ; putc ( '\n' , file ) ; } } } </s>

Output extern declarations for global symbols which are have been referenced but not defined .


<s> static void unicosmk_output_module_name ( FILE * file ) { const char * name = lbasename ( main_input_filename ) ; unsigned len = strlen ( name ) ; char * clean_name = alloca ( len + 2 ) ; char * ptr = clean_name ; if ( ! ISALPHA ( * name ) ) * ptr ++ = '$' ; memcpy ( ptr , name , len + 1 ) ; clean_symbol_name ( clean_name ) ; fputs ( clean_name , file ) ; } </s>

Output the module name for .ident and .end directives . We have to strip directories and add make sure that the module name starts with a letter or ' $ ' .


<s>
static
void
unicosmk_output_ssib
(
FILE
*
file
,
const
char
*
fnname
)
{
int
len
;
int
i
;
rtx
x
;
rtx
ciw
;
struct
machine_function
*
machine
=
cfun
->
machine
;
ssib_section
(
)
;
fprintf
(
file
,
"\t.endp\n\n\t.psect\t%s%s,data\n"
,
user_label_prefix
,
unicosmk_ssib_name
(
)
)
;
len
=
strlen
(
fnname
)
;
fprintf
(
file
,
"\t.quad\t^X20008%2.2X28\n"
,
len
)
;
fputs
(
"\t.quad\t0\n"
,
file
)
;
fputs
(
"\t.quad\t"
,
file
)
;
assemble_name
(
file
,
fnname
)
;
putc
(
'\n'
,
file
)
;
fputs
(
"\t.quad\t0\n"
,
file
)
;
fputs
(
"\t.quad\t0\n"
,
file
)
;
for
(
i
=
0
;
i
<
len
;
i
++
)
fprintf
(
file
,
"\t.byte\t%d\n"
,
(
int
)
(
fnname
[
i
]
)
)
;
if
(
(
len
%
8
)
==
0
)
fputs
(
"\t.quad\t0\n"
,
file
)
;
else
fprintf
(
file
,
"\t.bits\t%d : 0\n"
,
(
8
(
len
%
8
)
)
*
8
)
;
for
(
x
=
machine
->
first_ciw
;
x
;
x
=
XEXP
(
x
,
1
)
)
{
ciw
=
XEXP
(
x
,
0
)
;
fprintf
(
file
,
"\t.quad\t"
HOST_WIDE_INT_PRINT_DOUBLE_HEX
"\n"
,
CONST_DOUBLE_HIGH
(
ciw
)
,
CONST_DOUBLE_LOW
(
ciw
)
)
;
fprintf
(
file
,
"\t.quad\t"
HOST_WIDE_INT_PRINT_HEX
"\n"
,
INTVAL
(
ciw
)
)
;
}
}
</s>

Output the static subroutine information block for the current function .


Check if NAME must be replaced by a DEX expression .


<s> static const char * unicosmk_ssib_name ( void ) { static char name [ 256 ] ; rtx x ; const char * fnname ; int len ; x = DECL_RTL ( cfun -> decl ) ; gcc_assert ( GET_CODE ( x ) == MEM ) ; x = XEXP ( x , 0 ) ; gcc_assert ( GET_CODE ( x ) == SYMBOL_REF ) ; fnname = XSTR ( x , 0 ) ; len = strlen ( fnname ) ; if ( len + SSIB_PREFIX_LEN > 255 ) len = 255 - SSIB_PREFIX_LEN ; strcpy ( name , SSIB_PREFIX ) ; strncpy ( name + SSIB_PREFIX_LEN , fnname , len ) ; name [ len + SSIB_PREFIX_LEN ] = 0 ; return name ; } </s>

Generate the name of the SSIB section for the current function .


<s> static void unicosmk_unique_section ( tree decl , int reloc ATTRIBUTE_UNUSED ) { const char * name ; int len ; gcc_assert ( decl ) ; name = IDENTIFIER_POINTER ( DECL_ASSEMBLER_NAME ( decl ) ) ; name = default_strip_name_encoding ( name ) ; len = strlen ( name ) ; if ( TREE_CODE ( decl ) == FUNCTION_DECL ) { char * string ; string = alloca ( len + 6 ) ; sprintf ( string , "code@%s" , name ) ; DECL_SECTION_NAME ( decl ) = build_string ( len + 5 , string ) ; } else if ( TREE_PUBLIC ( decl ) ) DECL_SECTION_NAME ( decl ) = build_string ( len , name ) ; else { char * string ; string = alloca ( len + 6 ) ; sprintf ( string , "data@%s" , name ) ; DECL_SECTION_NAME ( decl ) = build_string ( len + 5 , string ) ; } } </s>

Generate a section name for decl and associate it with the declaration .


<s> static tree va_list_skip_additions ( tree lhs ) { tree rhs , stmt ; if ( TREE_CODE ( lhs ) != SSA_NAME ) return lhs ; for ( ; ; ) { stmt = SSA_NAME_DEF_STMT ( lhs ) ; if ( TREE_CODE ( stmt ) == PHI_NODE ) return stmt ; if ( TREE_CODE ( stmt ) != MODIFY_EXPR || TREE_OPERAND ( stmt , 0 ) != lhs ) return lhs ; rhs = TREE_OPERAND ( stmt , 1 ) ; if ( TREE_CODE ( rhs ) == WITH_SIZE_EXPR ) rhs = TREE_OPERAND ( rhs , 0 ) ; if ( ( TREE_CODE ( rhs ) != NOP_EXPR && TREE_CODE ( rhs ) != CONVERT_EXPR && ( TREE_CODE ( rhs ) != PLUS_EXPR || TREE_CODE ( TREE_OPERAND ( rhs , 1 ) ) != INTEGER_CST || ! host_integerp ( TREE_OPERAND ( rhs , 1 ) , 1 ) ) ) || TREE_CODE ( TREE_OPERAND ( rhs , 0 ) ) != SSA_NAME ) return rhs ; lhs = TREE_OPERAND ( rhs , 0 ) ; } } </s>

Helper function for alpha_stdarg_optimize_hook . Skip over casts and constant additions .


<s> static void vms_asm_named_section ( const char * name , unsigned int flags , tree decl ATTRIBUTE_UNUSED ) { fputc ( '\n' , asm_out_file ) ; fprintf ( asm_out_file , ".section\t%s" , name ) ; if ( flags & SECTION_VMS_OVERLAY ) fprintf ( asm_out_file , ",OVR" ) ; if ( flags & SECTION_VMS_GLOBAL ) fprintf ( asm_out_file , ",GBL" ) ; if ( flags & SECTION_VMS_INITIALIZE ) fprintf ( asm_out_file , ",NOMOD" ) ; if ( flags & SECTION_DEBUG ) fprintf ( asm_out_file , ",NOWRT" ) ; fputc ( '\n' , asm_out_file ) ; } </s>

Switch to an arbitrary section NAME with attributes as specified by FLAGS . ALIGN specifies any known alignment requirements for the section ; 0 if the default should be used .

alpha ".section\t%s" ",OVR" ",GBL" ",NOMOD" ",NOWRT"


<s> static void vms_asm_out_constructor ( rtx symbol , int priority ATTRIBUTE_UNUSED ) { ctors_section ( ) ; assemble_align ( BITS_PER_WORD ) ; assemble_integer ( symbol , UNITS_PER_WORD , BITS_PER_WORD , 1 ) ; } </s>


<s> static int alpha_adjust_cost ( rtx_insn * insn , rtx link , rtx_insn * dep_insn , int cost ) { enum attr_type dep_insn_type ; if ( REG_NOTE_KIND ( link ) != 0 ) return cost ; if ( recog_memoized ( insn ) < 0 || recog_memoized ( dep_insn ) < 0 ) return cost ; dep_insn_type = get_attr_type ( dep_insn ) ; if ( dep_insn_type == TYPE_ILD || dep_insn_type == TYPE_FLD || dep_insn_type == TYPE_LDSYM ) cost += alpha_memory_latency - 1 ; return cost ; } </s>

Adjust the cost of a scheduling dependency . Return the new cost of a dependency LINK or INSN on DEP_INSN . COST is the current cost .


<s> static void alpha_align_insns_1 ( unsigned int max_align , rtx_insn * ( * next_group ) ( rtx_insn * , int * , int * ) , rtx ( * next_nop ) ( int * ) ) { unsigned int align ; int ofs ; int prev_in_use , in_use , len , ldgp ; rtx_insn * i , * next ; shorten_branches ( get_insns ( ) ) ; if ( align_functions < 4 ) align = 4 ; else if ( ( unsigned int ) align_functions < max_align ) align = align_functions ; else align = max_align ; ofs = prev_in_use = 0 ; i = get_insns ( ) ; if ( NOTE_P ( i ) ) i = next_nonnote_insn ( i ) ; ldgp = alpha_function_needs_gp ? 8 : 0 ; while ( i ) { next = ( * next_group ) ( i , & in_use , & len ) ; if ( LABEL_P ( i ) ) { unsigned int new_align = 1 << label_to_alignment ( i ) ; if ( new_align >= align ) { align = new_align < max_align ? new_align : max_align ; ofs = 0 ; } else if ( ofs & ( new_align - 1 ) ) ofs = ( ofs | ( new_align - 1 ) ) + 1 ; gcc_assert ( ! len ) ; } else if ( in_use == 0 ) { if ( len < 0 ) { ofs = 0 ; align = 4 ; len = 0 ; } } else if ( ( int ) align < len ) { unsigned int new_log_align = len > 8 ? 4 : 3 ; rtx_insn * prev , * where ; where = prev = prev_nonnote_insn ( i ) ; if ( ! where || ! LABEL_P ( where ) ) where = i ; if ( ! ( TARGET_EXPLICIT_RELOCS && prev && CALL_P ( prev ) ) ) { emit_insn_before ( gen_realign ( GEN_INT ( new_log_align ) ) , where ) ; align = 1 << new_log_align ; ofs = 0 ; } } else if ( ldgp > 0 ) ldgp -= len ; else if ( ofs + len > ( int ) align ) { int nop_count = ( align - ofs ) / 4 ; rtx_insn * where ; where = prev_nonnote_insn ( i ) ; if ( where ) { if ( LABEL_P ( where ) ) { rtx_insn * where2 = prev_nonnote_insn ( where ) ; if ( where2 && JUMP_P ( where2 ) ) where = where2 ; } else if ( NONJUMP_INSN_P ( where ) ) where = i ; } else where = i ; do emit_insn_before ( ( * next_nop ) ( & prev_in_use ) , where ) ; while ( -- nop_count ) ; ofs = 0 ; } ofs = ( ofs + len ) & ( align - 1 ) ; prev_in_use = in_use ; i = next ; } } </s>

The instruction group alignment main loop .


<s> enum avms_arg_type alpha_arg_type ( machine_mode mode ) { switch ( mode ) { case SFmode : return TARGET_FLOAT_VAX ? FF : FS ; case DFmode : return TARGET_FLOAT_VAX ? FD : FT ; default : return I64 ; } } </s>

Return the VMS argument type corresponding to MODE .


<s> static void alpha_canonicalize_comparison ( int * code , rtx * op0 , rtx * op1 , bool op0_preserve_value ) { if ( ! op0_preserve_value && ( * code == GE || * code == GT || * code == GEU || * code == GTU ) && ( REG_P ( * op1 ) || * op1 == const0_rtx ) ) { rtx tem = * op0 ; * op0 = * op1 ; * op1 = tem ; * code = ( int ) swap_condition ( ( enum rtx_code ) * code ) ; } if ( ( * code == LT || * code == LTU ) && CONST_INT_P ( * op1 ) && INTVAL ( * op1 ) == 256 ) { * code = * code == LT ? LE : LEU ; * op1 = GEN_INT ( 255 ) ; } } </s>

Canonicalize a comparison from one we do n't have to one we do have .


<s> bool alpha_emit_setcc ( rtx operands [ ] , machine_mode cmp_mode ) { enum rtx_code cmp_code ; enum rtx_code code = GET_CODE ( operands [ 1 ] ) ; rtx op0 = operands [ 2 ] , op1 = operands [ 3 ] ; rtx tmp ; if ( cmp_mode == TFmode ) { op0 = alpha_emit_xfloating_compare ( & code , op0 , op1 ) ; op1 = const0_rtx ; cmp_mode = DImode ; } if ( cmp_mode == DFmode && ! TARGET_FIX ) return 0 ; cmp_code = UNKNOWN ; switch ( code ) { case EQ : case LE : case LT : case LEU : case LTU : case UNORDERED : if ( cmp_mode == DFmode ) cmp_code = code , code = NE ; break ; case NE : if ( cmp_mode == DImode && op1 == const0_rtx ) break ; case ORDERED : cmp_code = reverse_condition ( code ) ; code = EQ ; break ; case GE : case GT : case GEU : case GTU : if ( cmp_mode == DImode && op1 == const0_rtx ) break ; code = swap_condition ( code ) ; if ( cmp_mode == DFmode ) cmp_code = code , code = NE ; std :: swap ( op0 , op1 ) ; break ; default : gcc_unreachable ( ) ; } if ( cmp_mode == DImode ) { if ( ! register_operand ( op0 , DImode ) ) op0 = force_reg ( DImode , op0 ) ; if ( ! reg_or_8bit_operand ( op1 , DImode ) ) op1 = force_reg ( DImode , op1 ) ; } if ( cmp_code != UNKNOWN ) { tmp = gen_reg_rtx ( cmp_mode ) ; emit_insn ( gen_rtx_SET ( VOIDmode , tmp , gen_rtx_fmt_ee ( cmp_code , cmp_mode , op0 , op1 ) ) ) ; op0 = cmp_mode != DImode ? gen_lowpart ( DImode , tmp ) : tmp ; op1 = const0_rtx ; } emit_insn ( gen_rtx_SET ( VOIDmode , operands [ 0 ] , gen_rtx_fmt_ee ( code , DImode , op0 , op1 ) ) ) ; return true ; } </s>

Certain simplifications can be done to make invalid setcc operations valid . Return the final comparison , or NULL if we ca n't work .


<s> static void alpha_emit_xfloating_libcall ( rtx func , rtx target , rtx operands [ ] , int noperands , rtx equiv ) { rtx usage = NULL_RTX , tmp , reg ; int regno = 16 , i ; start_sequence ( ) ; for ( i = 0 ; i < noperands ; ++ i ) { switch ( GET_MODE ( operands [ i ] ) ) { case TFmode : reg = gen_rtx_REG ( TFmode , regno ) ; regno += 2 ; break ; case DFmode : reg = gen_rtx_REG ( DFmode , regno + 32 ) ; regno += 1 ; break ; case VOIDmode : gcc_assert ( CONST_INT_P ( operands [ i ] ) ) ; case DImode : reg = gen_rtx_REG ( DImode , regno ) ; regno += 1 ; break ; default : gcc_unreachable ( ) ; } emit_move_insn ( reg , operands [ i ] ) ; use_reg ( & usage , reg ) ; } switch ( GET_MODE ( target ) ) { case TFmode : reg = gen_rtx_REG ( TFmode , 16 ) ; break ; case DFmode : reg = gen_rtx_REG ( DFmode , 32 ) ; break ; case DImode : reg = gen_rtx_REG ( DImode , 0 ) ; break ; default : gcc_unreachable ( ) ; } tmp = gen_rtx_MEM ( QImode , func ) ; tmp = emit_call_insn ( GEN_CALL_VALUE ( reg , tmp , const0_rtx , const0_rtx , const0_rtx ) ) ; CALL_INSN_FUNCTION_USAGE ( tmp ) = usage ; RTL_CONST_CALL_P ( tmp ) = 1 ; tmp = get_insns ( ) ; end_sequence ( ) ; emit_libcall_block ( tmp , target , reg , equiv ) ; } </s>

Emit an X_floating library function call . Note that these functions do not follow normal calling conventions : TFmode arguments are passed in two integer registers ( as opposed to indirect ) ; TFmode return values appear in R16+R17 . FUNC is the function name to call . TARGET is where the output belongs . OPERANDS are the inputs . NOPERANDS is the count of inputs . EQUIV is the expression equivalent for the function .


<s>
static
rtx
alpha_expand_builtin
(
tree
exp
,
rtx
target
,
rtx
subtarget
ATTRIBUTE_UNUSED
,
machine_mode
mode
ATTRIBUTE_UNUSED
,
int
ignore
ATTRIBUTE_UNUSED
)
{
tree
fndecl
=
TREE_OPERAND
(
CALL_EXPR_FN
(
exp
)
,
0
)
;
unsigned
int
fcode
=
DECL_FUNCTION_CODE
(
fndecl
)
;
tree
arg
;
call_expr_arg_iterator
iter
;
enum
insn_code
icode
;
rtx
op
[
MAX_ARGS
]
,
pat
;
int
arity
;
bool
nonvoid
;
if
(
fcode
>=
ALPHA_BUILTIN_max
)
internal_error
(
"bad builtin fcode"
)
;
icode
=
code_for_builtin
[
fcode
]
;
if
(
icode
==
0
)
internal_error
(
"bad builtin fcode"
)
;
nonvoid
=
TREE_TYPE
(
TREE_TYPE
(
fndecl
)
)
!=
void_type_node
;
arity
=
0
;
FOR_EACH_CALL_EXPR_ARG
(
arg
,
iter
,
exp
)
{
const
struct
insn_operand_data
*
insn_op
;
if
(
arg
==
error_mark_node
)
return
NULL_RTX
;
if
(
arity
>
MAX_ARGS
)
return
NULL_RTX
;
insn_op
=
&
insn_data
[
icode
]
.
operand
[
arity
+
nonvoid
]
;
op
[
arity
]
=
expand_expr
(
arg
,
NULL_RTX
,
insn_op
->
mode
,
EXPAND_NORMAL
)
;
if
(
!
(
*
insn_op
->
predicate
)
(
op
[
arity
]
,
insn_op
->
mode
)
)
op
[
arity
]
=
copy_to_mode_reg
(
insn_op
->
mode
,
op
[
arity
]
)
;
arity
++
;
}
if
(
nonvoid
)
{
machine_mode
tmode
=
insn_data
[
icode
]
.
operand
[
0
]
.
mode
;
if
(
!
target
||
GET_MODE
(
target
)
!=
tmode
||
!
(
*
insn_data
[
icode
]
.
operand
[
0
]
.
predicate
)
(
target
,
tmode
)
)
target
=
gen_reg_rtx
(
tmode
)
;
}
switch
(
arity
)
{
case
0
:
pat
=
GEN_FCN
(
icode
)
(
target
)
;
break
;
case
1
:
if
(
nonvoid
)
pat
=
GEN_FCN
(
icode
)
(
target
,
op
[
0
]
)
;
else
pat
=
GEN_FCN
(
icode
)
(
op
[
0
]
)
;
break
;
case
2
:
pat
=
GEN_FCN
(
icode
)
(
target
,
op
[
0
]
,
op
[
1
]
)
;
break
;
default
:
gcc_unreachable
(
)
;
}
if
(
!
pat
)
return
NULL_RTX
;
emit_insn
(
pat
)
;
if
(
nonvoid
)
return
target
;
else
return
const0_rtx
;
}
</s>

Expand an expression EXP that calls a built-in function , with result going to TARGET if that 's convenient ( and in mode MODE if that 's convenient ) . SUBTARGET may be used as the target for computing one of EXP 's operands . IGNORE is nonzero if the value is to be ignored .


<s> bool alpha_expand_mov ( machine_mode mode , rtx * operands ) { rtx tmp ; if ( MEM_P ( operands [ 0 ] ) && ! reg_or_0_operand ( operands [ 1 ] , mode ) ) operands [ 1 ] = force_reg ( mode , operands [ 1 ] ) ; if ( mode == Pmode && symbolic_operand ( operands [ 1 ] , mode ) ) { tmp = alpha_legitimize_address_1 ( operands [ 1 ] , operands [ 0 ] , mode ) ; if ( tmp ) { if ( tmp == operands [ 0 ] ) return true ; operands [ 1 ] = tmp ; return false ; } } if ( ! CONSTANT_P ( operands [ 1 ] ) || input_operand ( operands [ 1 ] , mode ) ) return false ; if ( CONST_INT_P ( operands [ 1 ] ) || GET_CODE ( operands [ 1 ] ) == CONST_DOUBLE || GET_CODE ( operands [ 1 ] ) == CONST_VECTOR ) { if ( alpha_split_const_mov ( mode , operands ) ) return true ; } tmp = force_const_mem ( mode , operands [ 1 ] ) ; if ( tmp == NULL_RTX ) return false ; if ( reload_in_progress ) { emit_move_insn ( operands [ 0 ] , XEXP ( tmp , 0 ) ) ; operands [ 1 ] = replace_equiv_address ( tmp , operands [ 0 ] ) ; } else operands [ 1 ] = validize_mem ( tmp ) ; return false ; } </s>

Expand a move instruction ; return true if all work is done . We do n't handle non-bwx subword loads here .