<s> bool n7_consumed_by_ii_dep_p ( rtx_insn * consumer , rtx def_reg ) { rtx use_rtx ; switch ( get_attr_type ( consumer ) ) { case TYPE_ALU : if ( movd44_even_dep_p ( consumer , def_reg ) ) return true ; use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_MUL : use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_MAC : use_rtx = extract_mac_non_acc_rtx ( consumer ) ; break ; case TYPE_DIV : if ( divmod_p ( consumer ) ) use_rtx = SET_SRC ( parallel_element ( consumer , 0 ) ) ; else use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_LOAD : if ( post_update_insn_p ( consumer ) ) use_rtx = extract_base_reg ( consumer ) ; else use_rtx = extract_mem_rtx ( consumer ) ; break ; case TYPE_STORE : if ( post_update_insn_p ( consumer ) ) use_rtx = extract_base_reg ( consumer ) ; else use_rtx = extract_mem_rtx ( consumer ) ; if ( reg_overlap_p ( def_reg , use_rtx ) ) return true ; if ( ! post_update_insn_p ( consumer ) && ! immed_offset_p ( extract_mem_rtx ( consumer ) ) ) return false ; use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_LOAD_MULTIPLE : use_rtx = extract_base_reg ( consumer ) ; break ; case TYPE_STORE_MULTIPLE : use_rtx = extract_base_reg ( consumer ) ; if ( reg_overlap_p ( def_reg , use_rtx ) ) return true ; use_rtx = extract_nth_access_rtx ( consumer , 0 ) ; break ; case TYPE_BRANCH : use_rtx = PATTERN ( consumer ) ; break ; default : gcc_unreachable ( ) ; } if ( reg_overlap_p ( def_reg , use_rtx ) ) return true ; return false ; } </s>


<s> bool n8_consumed_by_addr_in_p ( rtx_insn * consumer , rtx def_reg ) { rtx use_rtx ; switch ( get_attr_type ( consumer ) ) { case TYPE_BRANCH : use_rtx = extract_branch_target_rtx ( consumer ) ; break ; case TYPE_LOAD : if ( load_single_p ( consumer ) ) use_rtx = extract_mem_rtx ( consumer ) ; else use_rtx = extract_base_reg ( consumer ) ; break ; case TYPE_STORE : if ( store_single_p ( consumer ) && ( ! post_update_insn_p ( consumer ) || immed_offset_p ( extract_mem_rtx ( consumer ) ) ) ) use_rtx = extract_mem_rtx ( consumer ) ; else use_rtx = extract_base_reg ( consumer ) ; break ; case TYPE_LOAD_MULTIPLE : case TYPE_STORE_MULTIPLE : use_rtx = extract_base_reg ( consumer ) ; break ; default : gcc_unreachable ( ) ; } return reg_overlap_p ( def_reg , use_rtx ) ; } </s>

Check the dependency between the producer defining DEF_REG and CONSUMER requiring input operand at AG ( II ) .


<s> bool n8_consumed_by_ex_p ( rtx_insn * consumer , rtx def_reg ) { rtx use_rtx ; switch ( get_attr_type ( consumer ) ) { case TYPE_ALU : if ( movd44_even_dep_p ( consumer , def_reg ) ) return true ; use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_MUL : use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_MAC : use_rtx = extract_mac_non_acc_rtx ( consumer ) ; break ; case TYPE_DIV : if ( divmod_p ( consumer ) ) use_rtx = SET_SRC ( parallel_element ( consumer , 0 ) ) ; else use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_BRANCH : use_rtx = extract_branch_condition_rtx ( consumer ) ; break ; case TYPE_STORE : if ( ! post_update_insn_p ( consumer ) && ! immed_offset_p ( extract_mem_rtx ( consumer ) ) ) return false ; use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_STORE_MULTIPLE : use_rtx = extract_nth_access_rtx ( consumer , 0 ) ; break ; default : gcc_unreachable ( ) ; } return reg_overlap_p ( def_reg , use_rtx ) ; } </s>

Check the dependency between the producer defining DEF_REG and CONSUMER requiring input operand at EX .


<s> bool n9_2r1w_consumed_by_ex_dep_p ( rtx_insn * consumer , rtx def_reg ) { rtx use_rtx ; switch ( get_attr_type ( consumer ) ) { case TYPE_ALU : if ( movd44_even_dep_p ( consumer , def_reg ) ) return true ; use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_PBSAD : case TYPE_MUL : use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_ALU_SHIFT : use_rtx = extract_shift_reg ( consumer ) ; break ; case TYPE_PBSADA : return pbsada_insn_ra_rb_dep_reg_p ( consumer , def_reg ) ; case TYPE_MAC : use_rtx = PATTERN ( consumer ) ; break ; case TYPE_DIV : if ( divmod_p ( consumer ) ) use_rtx = SET_SRC ( parallel_element ( consumer , 0 ) ) ; else use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_MMU : if ( GET_CODE ( PATTERN ( consumer ) ) == SET ) use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; else return true ; break ; case TYPE_LOAD : if ( post_update_insn_p ( consumer ) ) use_rtx = extract_base_reg ( consumer ) ; else use_rtx = extract_mem_rtx ( consumer ) ; break ; case TYPE_STORE : if ( post_update_insn_p ( consumer ) ) use_rtx = extract_base_reg ( consumer ) ; else use_rtx = extract_mem_rtx ( consumer ) ; if ( reg_overlap_p ( def_reg , use_rtx ) ) return true ; if ( ! post_update_insn_p ( consumer ) && ! immed_offset_p ( extract_mem_rtx ( consumer ) ) ) return false ; use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_LOAD_MULTIPLE : use_rtx = extract_base_reg ( consumer ) ; break ; case TYPE_STORE_MULTIPLE : use_rtx = extract_base_reg ( consumer ) ; if ( reg_overlap_p ( def_reg , use_rtx ) ) return true ; use_rtx = extract_nth_access_rtx ( consumer , 0 ) ; break ; case TYPE_BRANCH : use_rtx = PATTERN ( consumer ) ; break ; default : gcc_unreachable ( ) ; } if ( reg_overlap_p ( def_reg , use_rtx ) ) return true ; return false ; } </s>


<s> bool n9_3r2w_consumed_by_ex_dep_p ( rtx_insn * consumer , rtx def_reg ) { rtx use_rtx ; switch ( get_attr_type ( consumer ) ) { case TYPE_ALU : case TYPE_PBSAD : case TYPE_MUL : use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_ALU_SHIFT : use_rtx = extract_shift_reg ( consumer ) ; break ; case TYPE_PBSADA : return pbsada_insn_ra_rb_dep_reg_p ( consumer , def_reg ) ; case TYPE_MAC : use_rtx = extract_mac_non_acc_rtx ( consumer ) ; break ; case TYPE_DIV : if ( divmod_p ( consumer ) ) use_rtx = SET_SRC ( parallel_element ( consumer , 0 ) ) ; else use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; break ; case TYPE_MMU : if ( GET_CODE ( PATTERN ( consumer ) ) == SET ) use_rtx = SET_SRC ( PATTERN ( consumer ) ) ; else return true ; break ; case TYPE_LOAD : case TYPE_STORE : use_rtx = extract_mem_rtx ( consumer ) ; break ; case TYPE_LOAD_MULTIPLE : case TYPE_STORE_MULTIPLE : use_rtx = extract_base_reg ( consumer ) ; break ; case TYPE_BRANCH : use_rtx = PATTERN ( consumer ) ; break ; default : gcc_unreachable ( ) ; } if ( reg_overlap_p ( def_reg , use_rtx ) ) return true ; return false ; } </s>


<s> bool nds32_e8_load_to_ii_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx def_reg = SET_DEST ( PATTERN ( producer ) ) ; return e8_consumed_by_addr_in_p ( consumer , def_reg ) ; } </s>


<s> bool nds32_gw_ex_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { return nds32_n10_ex_to_ex_p ( producer , consumer ) ; } </s>

Check dependencies from EX to EX ( ADDR_OUT - > ADDR_IN ) .


<s> bool nds32_gw_last_load_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx last_def_reg = extract_nth_access_reg ( producer , - 1 ) ; return gw_consumed_by_ex_dep_p ( consumer , last_def_reg ) ; } </s>

Check dependencies from LMW ( N , N ) to EX .


<s> bool nds32_gw_mm_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx def_reg ; switch ( get_attr_type ( producer ) ) { case TYPE_LOAD : case TYPE_MUL : case TYPE_MAC : case TYPE_DALU64 : case TYPE_DMUL : case TYPE_DMAC : case TYPE_DALUROUND : case TYPE_DBPICK : case TYPE_DWEXT : def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; case TYPE_DIV : if ( divmod_p ( producer ) ) { rtx def_reg1 = SET_DEST ( parallel_element ( producer , 0 ) ) ; rtx def_reg2 = SET_DEST ( parallel_element ( producer , 1 ) ) ; return ( gw_consumed_by_ex_dep_p ( consumer , def_reg1 ) || gw_consumed_by_ex_dep_p ( consumer , def_reg2 ) ) ; } def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; default : gcc_unreachable ( ) ; } return gw_consumed_by_ex_dep_p ( consumer , def_reg ) ; } </s>


<s> bool nds32_n10_ex_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { gcc_assert ( get_attr_type ( producer ) == TYPE_FLOAD || get_attr_type ( producer ) == TYPE_FSTORE ) ; gcc_assert ( get_attr_type ( consumer ) == TYPE_FLOAD || get_attr_type ( consumer ) == TYPE_FSTORE ) ; if ( ! post_update_insn_p ( producer ) ) return false ; return reg_overlap_p ( extract_base_reg ( producer ) , extract_mem_rtx ( consumer ) ) ; } </s>


<s> bool nds32_n10_last_load_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx last_def_reg = extract_nth_access_reg ( producer , - 1 ) ; return n10_consumed_by_ex_dep_p ( consumer , last_def_reg ) ; } </s>


<s> bool nds32_n10_mm_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx def_reg ; switch ( get_attr_type ( producer ) ) { case TYPE_LOAD : case TYPE_MUL : case TYPE_MAC : case TYPE_DALU64 : case TYPE_DMUL : case TYPE_DMAC : case TYPE_DALUROUND : case TYPE_DBPICK : case TYPE_DWEXT : def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; case TYPE_DIV : if ( divmod_p ( producer ) ) { rtx def_reg1 = SET_DEST ( parallel_element ( producer , 0 ) ) ; rtx def_reg2 = SET_DEST ( parallel_element ( producer , 1 ) ) ; return ( n10_consumed_by_ex_dep_p ( consumer , def_reg1 ) || n10_consumed_by_ex_dep_p ( consumer , def_reg2 ) ) ; } def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; default : gcc_unreachable ( ) ; } return n10_consumed_by_ex_dep_p ( consumer , def_reg ) ; } </s>


<s> bool nds32_n13_e2_to_e1_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx def_reg ; switch ( get_attr_type ( producer ) ) { case TYPE_LOAD : case TYPE_STORE : case TYPE_LOAD_MULTIPLE : case TYPE_STORE_MULTIPLE : if ( ! post_update_insn_p ( producer ) ) return false ; def_reg = extract_base_reg ( producer ) ; break ; case TYPE_ALU : case TYPE_ALU_SHIFT : case TYPE_PBSAD : case TYPE_PBSADA : case TYPE_MUL : case TYPE_MAC : def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; case TYPE_BRANCH : return true ; case TYPE_DIV : if ( divmod_p ( producer ) ) { rtx def_reg1 = SET_DEST ( parallel_element ( producer , 0 ) ) ; rtx def_reg2 = SET_DEST ( parallel_element ( producer , 1 ) ) ; return ( n13_consumed_by_e1_dep_p ( consumer , def_reg1 ) || n13_consumed_by_e1_dep_p ( consumer , def_reg2 ) ) ; } def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; default : gcc_unreachable ( ) ; } return n13_consumed_by_e1_dep_p ( consumer , def_reg ) ; } </s>


<s> bool nds32_n13_last_load_to_e1_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx last_def_reg = extract_nth_access_reg ( producer , - 1 ) ; return n13_consumed_by_e1_dep_p ( consumer , last_def_reg ) ; } </s>

Check dependencies from LMW ( N , N ) to E1 .


<s> bool nds32_n13_last_load_to_e2_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx last_def_reg = extract_nth_access_reg ( producer , - 1 ) ; return n13_consumed_by_e2_dep_p ( consumer , last_def_reg ) ; } </s>

Check dependencies from LMW ( N , N ) to E2 .


<s> bool nds32_n13_last_two_load_to_e1_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx last_two_def_reg = extract_nth_access_reg ( producer , - 2 ) ; if ( last_two_def_reg == NULL_RTX ) return false ; return n13_consumed_by_e1_dep_p ( consumer , last_two_def_reg ) ; } </s>

Check dependencies from LMW ( N , N-1 ) to E2 .


<s> bool nds32_n13_load_to_e1_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx def_reg = SET_DEST ( PATTERN ( producer ) ) ; gcc_assert ( get_attr_type ( producer ) == TYPE_LOAD ) ; gcc_assert ( REG_P ( def_reg ) || GET_CODE ( def_reg ) == SUBREG ) ; return n13_consumed_by_e1_dep_p ( consumer , def_reg ) ; } </s>

Check dependencies from Load-Store Unit ( E3 ) to E1 .


<s> bool nds32_n13_load_to_e2_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx def_reg = SET_DEST ( PATTERN ( producer ) ) ; gcc_assert ( get_attr_type ( producer ) == TYPE_LOAD ) ; gcc_assert ( REG_P ( def_reg ) || GET_CODE ( def_reg ) == SUBREG ) ; return n13_consumed_by_e2_dep_p ( consumer , def_reg ) ; } </s>

Check dependencies from Load-Store Unit ( E3 ) to E2 .


<s> bool nds32_n7_load_to_ii_p ( rtx_insn * producer , rtx_insn * consumer ) { if ( post_update_insn_p ( producer ) ) return false ; rtx def_reg = SET_DEST ( PATTERN ( producer ) ) ; return n7_consumed_by_ii_dep_p ( consumer , def_reg ) ; } </s>


<s> bool nds32_n8_load_to_ii_p ( rtx_insn * producer , rtx_insn * consumer ) { if ( post_update_insn_p ( producer ) ) return false ; rtx def_reg = SET_DEST ( PATTERN ( producer ) ) ; return n8_consumed_by_addr_in_p ( consumer , def_reg ) ; } </s>


<s> bool nds32_n9_2r1w_mm_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx def_reg ; switch ( get_attr_type ( producer ) ) { case TYPE_LOAD : if ( post_update_insn_p ( producer ) ) return false ; def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; case TYPE_MUL : case TYPE_MAC : def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; default : gcc_unreachable ( ) ; } return n9_2r1w_consumed_by_ex_dep_p ( consumer , def_reg ) ; } </s>


<s> bool nds32_n9_3r2w_mm_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx def_reg ; switch ( get_attr_type ( producer ) ) { case TYPE_LOAD : case TYPE_MUL : case TYPE_MAC : def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; case TYPE_DIV : if ( divmod_p ( producer ) ) { rtx def_reg1 = SET_DEST ( parallel_element ( producer , 0 ) ) ; rtx def_reg2 = SET_DEST ( parallel_element ( producer , 1 ) ) ; return ( n9_3r2w_consumed_by_ex_dep_p ( consumer , def_reg1 ) || n9_3r2w_consumed_by_ex_dep_p ( consumer , def_reg2 ) ) ; } def_reg = SET_DEST ( PATTERN ( producer ) ) ; break ; default : gcc_unreachable ( ) ; } return n9_3r2w_consumed_by_ex_dep_p ( consumer , def_reg ) ; } </s>


<s> bool nds32_n9_last_load_to_ex_p ( rtx_insn * producer , rtx_insn * consumer ) { rtx last_def_reg = extract_nth_access_reg ( producer , - 1 ) ; if ( nds32_register_ports_config == REG_PORT_2R1W ) { if ( post_update_insn_p ( producer ) ) return false ; size_t i ; size_t n_elems = parallel_elements ( producer ) ; rtx base_reg = extract_base_reg ( producer ) ; for ( i = 0 ; i < n_elems ; ++ i ) { rtx load_rtx = extract_nth_access_rtx ( producer , i ) ; rtx list_element = SET_DEST ( load_rtx ) ; if ( rtx_equal_p ( base_reg , list_element ) && i != n_elems - 1 ) { last_def_reg = base_reg ; break ; } } return n9_2r1w_consumed_by_ex_dep_p ( consumer , last_def_reg ) ; } else return n9_3r2w_consumed_by_ex_dep_p ( consumer , last_def_reg ) ; } </s>


<s> bool pbsada_insn_ra_rb_dep_reg_p ( rtx pbsada_insn , rtx def_reg ) { rtx unspec_rtx = SET_SRC ( PATTERN ( pbsada_insn ) ) ; gcc_assert ( GET_CODE ( unspec_rtx ) == UNSPEC ) ; rtx pbsada_ra = XVECEXP ( unspec_rtx , 0 , 0 ) ; rtx pbsada_rb = XVECEXP ( unspec_rtx , 0 , 1 ) ; if ( rtx_equal_p ( def_reg , pbsada_ra ) || rtx_equal_p ( def_reg , pbsada_rb ) ) return true ; return false ; } </s>

Determine if the latency is occured when the consumer PBSADA_INSN uses the value of DEF_REG in its Ra or Rb fields .


<s> bool pbsada_insn_rt_dep_reg_p ( rtx pbsada_insn , rtx def_reg ) { rtx pbsada_rt = SET_DEST ( PATTERN ( pbsada_insn ) ) ; if ( rtx_equal_p ( def_reg , pbsada_rt ) ) return true ; return false ; } </s>

Determine if the latency is occured when the consumer PBSADA_INSN uses the value of DEF_REG in its Rt field .


<s> bool reg_overlap_p ( rtx x , rtx in ) { if ( x == NULL_RTX || in == NULL_RTX ) return false ; return static_cast < bool > ( reg_overlap_mentioned_p ( x , in ) ) ; } </s>

A safe wrapper to the function reg_overlap_mentioned_p ( ) .


<s> bool wext_odd_dep_p ( rtx insn , rtx def_reg ) { rtx shift_rtx = XEXP ( SET_SRC ( PATTERN ( insn ) ) , 0 ) ; rtx use_reg = XEXP ( shift_rtx , 0 ) ; rtx pos_rtx = XEXP ( shift_rtx , 1 ) ; if ( REG_P ( pos_rtx ) && reg_overlap_p ( def_reg , pos_rtx ) ) return true ; if ( GET_MODE ( def_reg ) == DImode ) return reg_overlap_p ( def_reg , use_reg ) ; gcc_assert ( REG_P ( def_reg ) || GET_CODE ( def_reg ) == SUBREG ) ; gcc_assert ( REG_P ( use_reg ) || GET_CODE ( use_reg ) == SUBREG ) ; if ( REG_P ( def_reg ) ) { if REG_P ( use_reg ) { if ( ! TARGET_BIG_ENDIAN ) return REGNO ( def_reg ) == REGNO ( use_reg ) + 1 ; else return REGNO ( def_reg ) == REGNO ( use_reg ) ; } else return true ; } if ( GET_CODE ( def_reg ) == SUBREG ) { if ( ! reg_overlap_p ( def_reg , use_reg ) ) return false ; if ( GET_CODE ( use_reg ) == SUBREG ) return true ; if ( ! TARGET_BIG_ENDIAN ) return SUBREG_BYTE ( def_reg ) == 4 ; else return SUBREG_BYTE ( def_reg ) == 0 ; } return false ; } </s>

Check if INSN is a wext insn consuming DEF_REG .


<s> int nds32_can_use_bclr_p ( int ival ) { int one_bit_count ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ~ ival ) ) ; return ( TARGET_PERF_EXT && ( one_bit_count == 1 ) ) ; } </s>

Function to check if 'bclr ' instruction can be used with IVAL .


<s> int nds32_can_use_bitci_p ( int ival ) { return ( TARGET_ISA_V3 && ( ival < 0 ) && satisfies_constraint_Iu15 ( gen_int_mode ( ~ ival , SImode ) ) ) ; } </s>

Function to check if 'bitci ' instruction can be used with IVAL .


<s> int nds32_can_use_bset_p ( int ival ) { int one_bit_count ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ival ) ) ; return ( TARGET_PERF_EXT && ( one_bit_count == 1 ) ) ; } </s>

Function to check if 'bset ' instruction can be used with IVAL .


<s> int nds32_can_use_btgl_p ( int ival ) { int one_bit_count ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ival ) ) ; return ( TARGET_PERF_EXT && ( one_bit_count == 1 ) ) ; } </s>

Function to check if 'btgl ' instruction can be used with IVAL .


Function to check whether the OP is a valid load/store operation . This is a helper function for the predicates : 'nds32_load_multiple_operation ' and 'nds32_store_multiple_operation ' in predicates.md file . The OP is supposed to be a parallel rtx . For each element within this parallel rtx : ( set ( reg ) ( mem addr ) ) is the form for load operation . ( set ( mem addr ) ( reg ) ) is the form for store operation . We have to extract reg and mem of every element and check if the information is valid for multiple load/store operation .


<s> int nds32_can_use_bclr_p ( int ival ) { int one_bit_count ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ~ ival ) ) ; return ( TARGET_EXT_PERF && ( one_bit_count == 1 ) ) ; } </s>


<s> int nds32_can_use_bset_p ( int ival ) { int one_bit_count ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ival ) ) ; return ( TARGET_EXT_PERF && ( one_bit_count == 1 ) ) ; } </s>


<s> int nds32_can_use_btgl_p ( int ival ) { int one_bit_count ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ival ) ) ; return ( TARGET_EXT_PERF && ( one_bit_count == 1 ) ) ; } </s>


<s> bool nds32_can_use_bclr_p ( HOST_WIDE_INT ival ) { int one_bit_count ; unsigned HOST_WIDE_INT mask = GET_MODE_MASK ( SImode ) ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ~ ival ) & mask ) ; return ( TARGET_EXT_PERF && ( one_bit_count == 1 ) ) ; } </s>


<s> bool nds32_can_use_bitci_p ( HOST_WIDE_INT ival ) { return ( TARGET_ISA_V3 && ( ival < 0 ) && satisfies_constraint_Iu15 ( gen_int_mode ( ~ ival , SImode ) ) ) ; } </s>


<s> bool nds32_can_use_bset_p ( HOST_WIDE_INT ival ) { int one_bit_count ; unsigned HOST_WIDE_INT mask = GET_MODE_MASK ( SImode ) ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ival ) & mask ) ; return ( TARGET_EXT_PERF && ( one_bit_count == 1 ) ) ; } </s>


<s> bool nds32_can_use_btgl_p ( HOST_WIDE_INT ival ) { int one_bit_count ; unsigned HOST_WIDE_INT mask = GET_MODE_MASK ( SImode ) ; one_bit_count = popcount_hwi ( ( unsigned HOST_WIDE_INT ) ( ival ) & mask ) ; return ( TARGET_EXT_PERF && ( one_bit_count == 1 ) ) ; } </s>


A subroutine that checks multiple load and store using consecutive registers . OP is a parallel rtx we would like to check . LOAD_P indicates whether we are checking load operation . PAR_INDEX is starting element of parallel rtx . FIRST_ELT_REGNO is used to tell starting register number . COUNT helps us to check consecutive register numbers .


<s> bool nds32_float_mem_operand_p ( rtx op ) { machine_mode mode = GET_MODE ( op ) ; rtx addr = XEXP ( op , 0 ) ; if ( GET_CODE ( addr ) == SYMBOL_REF || GET_CODE ( addr ) == CONST || GET_CODE ( addr ) == LO_SUM ) return false ; if ( GET_CODE ( addr ) == PLUS ) { if ( GET_CODE ( XEXP ( addr , 0 ) ) == SYMBOL_REF ) return false ; if ( GET_CODE ( XEXP ( addr , 1 ) ) == CONST_INT ) { if ( ( mode == SImode || mode == SFmode ) && NDS32_SINGLE_WORD_ALIGN_P ( INTVAL ( XEXP ( addr , 1 ) ) ) && ! satisfies_constraint_Is14 ( XEXP ( addr , 1 ) ) ) return false ; if ( ( mode == DImode || mode == DFmode ) && NDS32_DOUBLE_WORD_ALIGN_P ( INTVAL ( XEXP ( addr , 1 ) ) ) && ! satisfies_constraint_Is14 ( XEXP ( addr , 1 ) ) ) return false ; } } return true ; } </s>

Vaild memory operand for floating-point loads and stores


<s> bool nds32_symbol_load_store_p ( rtx_insn * insn ) { rtx mem_src = NULL_RTX ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD : mem_src = SET_SRC ( PATTERN ( insn ) ) ; break ; case TYPE_STORE : mem_src = SET_DEST ( PATTERN ( insn ) ) ; break ; default : break ; } if ( mem_src != NULL_RTX ) { if ( ( GET_CODE ( mem_src ) == ZERO_EXTEND ) || ( GET_CODE ( mem_src ) == SIGN_EXTEND ) ) mem_src = XEXP ( mem_src , 0 ) ; if ( ( GET_CODE ( XEXP ( mem_src , 0 ) ) == SYMBOL_REF ) || ( GET_CODE ( XEXP ( mem_src , 0 ) ) == LO_SUM ) ) return true ; } return false ; } </s>

Return true if is load/store with SYMBOL_REF addressing mode and memory mode is SImode .


<s> static void nds32_group_insns ( rtx sethi ) { df_ref def_record , use_record ; df_link * link ; rtx_insn * use_insn = NULL ; rtx group_id ; def_record = DF_INSN_DEFS ( sethi ) ; for ( link = DF_REF_CHAIN ( def_record ) ; link ; link = link -> next ) { if ( ! DF_REF_INSN_INFO ( link -> ref ) ) continue ; use_insn = DF_REF_INSN ( link -> ref ) ; if ( ! dominated_by_p ( CDI_DOMINATORS , BLOCK_FOR_INSN ( use_insn ) , BLOCK_FOR_INSN ( sethi ) ) ) return ; use_record = DF_INSN_USES ( use_insn ) ; if ( DF_REF_CHAIN ( use_record ) && DF_REF_CHAIN ( use_record ) -> next ) return ; if ( ! active_insn_p ( use_insn ) ) return ; if ( ! ( recog_memoized ( use_insn ) == CODE_FOR_lo_sum || nds32_symbol_load_store_p ( use_insn ) || ( nds32_reg_base_load_store_p ( use_insn ) && ! nds32_sp_base_or_plus_load_store_p ( use_insn ) ) ) ) return ; } group_id = GEN_INT ( relax_group_id ) ; emit_insn_before ( gen_relax_group ( group_id ) , sethi ) ; for ( link = DF_REF_CHAIN ( def_record ) ; link ; link = link -> next ) { if ( ! DF_REF_INSN_INFO ( link -> ref ) ) continue ; use_insn = DF_REF_INSN ( link -> ref ) ; if ( active_insn_p ( use_insn ) ) emit_insn_before ( gen_relax_group ( group_id ) , use_insn ) ; } relax_group_id ++ ; } </s>

Group the relax candidates with group id .


<s> static void nds32_relax_group ( void ) { rtx_insn * insn ; compute_bb_for_insn ( ) ; df_chain_add_problem ( DF_DU_CHAIN | DF_UD_CHAIN ) ; df_insn_rescan_all ( ) ; df_analyze ( ) ; df_set_flags ( DF_DEFER_INSN_RESCAN ) ; calculate_dominance_info ( CDI_DOMINATORS ) ; insn = get_insns ( ) ; gcc_assert ( NOTE_P ( insn ) ) ; for ( insn = next_active_insn ( insn ) ; insn ; insn = next_active_insn ( insn ) ) { if ( NONJUMP_INSN_P ( insn ) ) { if ( recog_memoized ( insn ) == CODE_FOR_sethi && nds32_symbolic_operand ( XEXP ( SET_SRC ( PATTERN ( insn ) ) , 0 ) , SImode ) ) nds32_group_insns ( insn ) ; } } df_insn_rescan_all ( ) ; df_finish_pass ( false ) ; free_dominance_info ( CDI_DOMINATORS ) ; } </s>

Group the relax candidate instructions for linker .


<s> unsigned int execute ( function * ) { return nds32_relax_opt ( ) ; } </s>


<s> int nds32_alloc_relax_group_id ( ) { return relax_group_id ++ ; } </s>

Group the following pattern as relax candidates : 1. sethi $ ra , hi20 ( sym ) ori $ ra , $ ra , lo12 ( sym ) == > addi.gp $ ra , sym 2. sethi $ ra , hi20 ( sym ) lwi $ rb , [ $ ra + lo12 ( sym ) ] == > lwi.gp $ rb , [ ( sym ) ] 3. sethi $ ra , hi20 ( sym ) ori $ ra , $ ra , lo12 ( sym ) lwi $ rb , [ $ ra ] swi $ rc , [ $ ra ] == > lwi37 $ rb , [ ( sym ) ] swi37 $ rc , [ ( sym ) ]


<s> static void nds32_group_float_insns ( rtx_insn * insn ) { df_ref def_record , use_record ; df_link * link ; rtx_insn * use_insn = NULL ; rtx group_id ; def_record = DF_INSN_DEFS ( insn ) ; for ( link = DF_REF_CHAIN ( def_record ) ; link ; link = link -> next ) { if ( ! DF_REF_INSN_INFO ( link -> ref ) ) continue ; use_insn = DF_REF_INSN ( link -> ref ) ; if ( ! dominated_by_p ( CDI_DOMINATORS , BLOCK_FOR_INSN ( use_insn ) , BLOCK_FOR_INSN ( insn ) ) ) return ; use_record = DF_INSN_USES ( use_insn ) ; if ( DF_REF_CHAIN ( use_record ) && DF_REF_CHAIN ( use_record ) -> next ) return ; if ( ! active_insn_p ( use_insn ) ) return ; if ( ! nds32_float_reg_load_store_p ( use_insn ) || find_post_update_rtx ( use_insn ) != - 1 ) return ; } group_id = GEN_INT ( nds32_alloc_relax_group_id ( ) ) ; emit_insn_before ( gen_relax_group ( group_id ) , insn ) ; for ( link = DF_REF_CHAIN ( def_record ) ; link ; link = link -> next ) { if ( ! DF_REF_INSN_INFO ( link -> ref ) ) continue ; use_insn = DF_REF_INSN ( link -> ref ) ; emit_insn_before ( gen_relax_group ( group_id ) , use_insn ) ; } } </s>

Group float load-store instructions : la $ ra , symbol flsi $ rt , [ $ ra + offset ]


<s> static void nds32_group_insns ( rtx_insn * sethi ) { df_ref def_record , use_record ; df_link * link ; rtx_insn * use_insn = NULL ; rtx group_id ; bool valid ; def_record = DF_INSN_DEFS ( sethi ) ; for ( link = DF_REF_CHAIN ( def_record ) ; link ; link = link -> next ) { if ( ! DF_REF_INSN_INFO ( link -> ref ) ) continue ; use_insn = DF_REF_INSN ( link -> ref ) ; if ( ! dominated_by_p ( CDI_DOMINATORS , BLOCK_FOR_INSN ( use_insn ) , BLOCK_FOR_INSN ( sethi ) ) ) return ; use_record = DF_INSN_USES ( use_insn ) ; if ( DF_REF_CHAIN ( use_record ) && DF_REF_CHAIN ( use_record ) -> next ) return ; if ( ! active_insn_p ( use_insn ) ) return ; if ( ! ( recog_memoized ( use_insn ) == CODE_FOR_lo_sum || nds32_symbol_load_store_p ( use_insn ) || ( nds32_reg_base_load_store_p ( use_insn ) && ! nds32_sp_base_or_plus_load_store_p ( use_insn ) ) ) ) return ; } group_id = GEN_INT ( nds32_alloc_relax_group_id ( ) ) ; emit_insn_before ( gen_relax_group ( group_id ) , sethi ) ; for ( link = DF_REF_CHAIN ( def_record ) ; link ; link = link -> next ) { if ( ! DF_REF_INSN_INFO ( link -> ref ) ) continue ; use_insn = DF_REF_INSN ( link -> ref ) ; if ( active_insn_p ( use_insn ) ) emit_insn_before ( gen_relax_group ( group_id ) , use_insn ) ; if ( use_insn != NULL && recog_memoized ( use_insn ) == CODE_FOR_lo_sum && ! nds32_const_unspec_p ( XEXP ( SET_SRC ( PATTERN ( use_insn ) ) , 1 ) ) ) { int sym_type = nds32_pic_tls_symbol_type ( use_insn ) ; valid = nds32_pic_tls_group ( use_insn , RELAX_ORI , sym_type ) ; while ( ! nds32_group_infos . is_empty ( ) ) { use_insn = nds32_group_infos . pop ( ) ; if ( valid ) emit_insn_before ( gen_relax_group ( group_id ) , use_insn ) ; } } } } </s>


<s> static void nds32_group_tls_insn ( rtx insn ) { rtx pat = PATTERN ( insn ) ; rtx unspec_relax_group = XEXP ( XVECEXP ( pat , 0 , 1 ) , 0 ) ; int group_id = nds32_alloc_relax_group_id ( ) ; while ( GET_CODE ( pat ) != SET && GET_CODE ( pat ) == PARALLEL ) { pat = XVECEXP ( pat , 0 , 0 ) ; } if ( GET_CODE ( unspec_relax_group ) == UNSPEC && XINT ( unspec_relax_group , 1 ) == UNSPEC_VOLATILE_RELAX_GROUP ) { XVECEXP ( unspec_relax_group , 0 , 0 ) = GEN_INT ( group_id ) ; } } </s>


<s> static bool nds32_ict_const_p ( rtx x ) { if ( GET_CODE ( x ) == CONST ) { x = XEXP ( x , 0 ) ; return nds32_indirect_call_referenced_p ( x ) ; } return FALSE ; } </s>

Return true if x is const and the referance is ict symbol .


<s> static bool nds32_pic_tls_group ( rtx_insn * def_insn , enum nds32_relax_insn_type relax_type , int sym_type ) { df_ref def_record ; df_link * link ; rtx_insn * use_insn = NULL ; rtx pat , new_pat ; def_record = DF_INSN_DEFS ( def_insn ) ; for ( link = DF_REF_CHAIN ( def_record ) ; link ; link = link -> next ) { if ( ! DF_REF_INSN_INFO ( link -> ref ) ) continue ; use_insn = DF_REF_INSN ( link -> ref ) ; if ( ! dominated_by_p ( CDI_DOMINATORS , BLOCK_FOR_INSN ( use_insn ) , BLOCK_FOR_INSN ( def_insn ) ) ) return FALSE ; if ( ! active_insn_p ( use_insn ) ) return FALSE ; switch ( relax_type ) { case RELAX_ORI : if ( ( sym_type == UNSPEC_TLSLE || sym_type == UNSPEC_GOTOFF ) && ( recog_memoized ( use_insn ) == CODE_FOR_addsi3 ) ) { pat = XEXP ( PATTERN ( use_insn ) , 1 ) ; new_pat = gen_rtx_UNSPEC ( SImode , gen_rtvec ( 2 , XEXP ( pat , 0 ) , XEXP ( pat , 1 ) ) , UNSPEC_ADD32 ) ; validate_replace_rtx ( pat , new_pat , use_insn ) ; nds32_group_infos . safe_push ( use_insn ) ; } else if ( nds32_plus_reg_load_store_p ( use_insn ) && ! nds32_sp_base_or_plus_load_store_p ( use_insn ) ) nds32_group_infos . safe_push ( use_insn ) ; else return FALSE ; break ; default : return FALSE ; } } return TRUE ; } </s>

Group the PIC and TLS relax candidate instructions for linker .


<s> static bool nds32_plus_reg_load_store_p ( rtx_insn * insn ) { rtx mem_src = NULL_RTX ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD : mem_src = SET_SRC ( PATTERN ( insn ) ) ; break ; case TYPE_STORE : mem_src = SET_DEST ( PATTERN ( insn ) ) ; break ; default : break ; } if ( mem_src != NULL_RTX ) { if ( ( GET_CODE ( mem_src ) == ZERO_EXTEND ) || ( GET_CODE ( mem_src ) == SIGN_EXTEND ) ) mem_src = XEXP ( mem_src , 0 ) ; if ( ( GET_CODE ( XEXP ( mem_src , 0 ) ) == PLUS ) ) mem_src = XEXP ( mem_src , 0 ) ; else return false ; if ( GET_CODE ( XEXP ( mem_src , 0 ) ) == REG ) return true ; } return false ; } </s>

Return true if is load with [ REG + REG/CONST_INT ] addressing mode .


<s> static bool nds32_reg_base_load_store_p ( rtx_insn * insn ) { rtx mem_src = NULL_RTX ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD : mem_src = SET_SRC ( PATTERN ( insn ) ) ; break ; case TYPE_STORE : mem_src = SET_DEST ( PATTERN ( insn ) ) ; break ; default : break ; } if ( mem_src != NULL_RTX ) { if ( ( GET_CODE ( mem_src ) == ZERO_EXTEND ) || ( GET_CODE ( mem_src ) == SIGN_EXTEND ) ) mem_src = XEXP ( mem_src , 0 ) ; if ( GET_CODE ( XEXP ( mem_src , 0 ) ) == REG ) return true ; } return false ; } </s>

Return true if is load/store with REG addressing mode and memory mode is SImode .


<s> static void nds32_relax_group ( void ) { rtx_insn * insn ; compute_bb_for_insn ( ) ; df_chain_add_problem ( DF_DU_CHAIN | DF_UD_CHAIN ) ; df_insn_rescan_all ( ) ; df_analyze ( ) ; df_set_flags ( DF_DEFER_INSN_RESCAN ) ; calculate_dominance_info ( CDI_DOMINATORS ) ; insn = get_insns ( ) ; gcc_assert ( NOTE_P ( insn ) ) ; for ( insn = next_active_insn ( insn ) ; insn ; insn = next_active_insn ( insn ) ) { if ( NONJUMP_INSN_P ( insn ) ) { if ( recog_memoized ( insn ) == CODE_FOR_sethi && nds32_symbolic_operand ( XEXP ( SET_SRC ( PATTERN ( insn ) ) , 0 ) , SImode ) && ! nds32_ict_const_p ( XEXP ( SET_SRC ( PATTERN ( insn ) ) , 0 ) ) ) nds32_group_insns ( insn ) ; else if ( recog_memoized ( insn ) == CODE_FOR_tls_ie ) nds32_group_tls_insn ( insn ) ; else if ( TARGET_FPU_SINGLE && recog_memoized ( insn ) == CODE_FOR_move_addr && ! nds32_ict_const_p ( XEXP ( SET_SRC ( PATTERN ( insn ) ) , 0 ) ) ) { nds32_group_float_insns ( insn ) ; } } else if ( CALL_P ( insn ) && recog_memoized ( insn ) == CODE_FOR_tls_desc ) { nds32_group_tls_insn ( insn ) ; } } df_insn_rescan_all ( ) ; df_finish_pass ( false ) ; free_dominance_info ( CDI_DOMINATORS ) ; } </s>


<s> static bool nds32_sp_base_or_plus_load_store_p ( rtx_insn * insn ) { rtx mem_src = NULL_RTX ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD : mem_src = SET_SRC ( PATTERN ( insn ) ) ; break ; case TYPE_STORE : mem_src = SET_DEST ( PATTERN ( insn ) ) ; break ; default : break ; } if ( mem_src != NULL_RTX ) { if ( ( GET_CODE ( mem_src ) == ZERO_EXTEND ) || ( GET_CODE ( mem_src ) == SIGN_EXTEND ) ) mem_src = XEXP ( mem_src , 0 ) ; if ( ( GET_CODE ( XEXP ( mem_src , 0 ) ) == PLUS ) ) mem_src = XEXP ( mem_src , 0 ) ; if ( REG_P ( XEXP ( mem_src , 0 ) ) && ( ( frame_pointer_needed && REGNO ( XEXP ( mem_src , 0 ) ) == FP_REGNUM ) || REGNO ( XEXP ( mem_src , 0 ) ) == SP_REGNUM ) ) return true ; } return false ; } </s>

Return true if insn is a sp/fp base or sp/fp plus load-store instruction .


<s> rtx extract_base_reg ( rtx_insn * insn ) { int post_update_rtx_index ; rtx mem_rtx ; rtx plus_rtx ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD_MULTIPLE : post_update_rtx_index = find_post_update_rtx ( insn ) ; if ( post_update_rtx_index != - 1 ) return SET_DEST ( parallel_element ( insn , post_update_rtx_index ) ) ; mem_rtx = SET_SRC ( parallel_element ( insn , 0 ) ) ; break ; case TYPE_STORE_MULTIPLE : post_update_rtx_index = find_post_update_rtx ( insn ) ; if ( post_update_rtx_index != - 1 ) return SET_DEST ( parallel_element ( insn , post_update_rtx_index ) ) ; mem_rtx = SET_DEST ( parallel_element ( insn , 0 ) ) ; break ; case TYPE_LOAD : case TYPE_FLOAD : case TYPE_STORE : case TYPE_FSTORE : mem_rtx = extract_mem_rtx ( insn ) ; break ; default : gcc_unreachable ( ) ; } gcc_assert ( MEM_P ( mem_rtx ) ) ; if ( REG_P ( XEXP ( mem_rtx , 0 ) ) ) return XEXP ( mem_rtx , 0 ) ; plus_rtx = XEXP ( mem_rtx , 0 ) ; if ( GET_CODE ( plus_rtx ) == SYMBOL_REF || GET_CODE ( plus_rtx ) == CONST ) return NULL_RTX ; gcc_assert ( GET_CODE ( plus_rtx ) == PLUS || GET_CODE ( plus_rtx ) == POST_INC || GET_CODE ( plus_rtx ) == POST_DEC || GET_CODE ( plus_rtx ) == POST_MODIFY ) ; gcc_assert ( REG_P ( XEXP ( plus_rtx , 0 ) ) ) ; return XEXP ( plus_rtx , 0 ) ; } </s>

Extract the base register from load/store insns . The function returns NULL_RTX if the address is not consist of any registers .


<s> rtx extract_mac_non_acc_rtx ( rtx_insn * insn ) { rtx exp = SET_SRC ( PATTERN ( insn ) ) ; switch ( get_attr_type ( insn ) ) { case TYPE_MAC : if ( REG_P ( XEXP ( exp , 0 ) ) ) return XEXP ( exp , 1 ) ; else return XEXP ( exp , 0 ) ; default : gcc_unreachable ( ) ; } } </s>

Extract the rtx representing non-accumulation operands of a MAC insn .


<s> bool divmod_p ( rtx_insn * insn ) { gcc_assert ( get_attr_type ( insn ) == TYPE_DIV ) ; if ( INSN_CODE ( insn ) == CODE_FOR_divmodsi4 || INSN_CODE ( insn ) == CODE_FOR_udivmodsi4 ) return true ; return false ; } </s>

Check if the DIV insn needs two write ports .


<s> rtx extract_base_reg ( rtx_insn * insn ) { int post_update_rtx_index ; rtx mem_rtx ; rtx plus_rtx ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD_MULTIPLE : post_update_rtx_index = find_post_update_rtx ( insn ) ; if ( post_update_rtx_index != - 1 ) return SET_DEST ( parallel_element ( insn , post_update_rtx_index ) ) ; mem_rtx = SET_SRC ( parallel_element ( insn , 0 ) ) ; break ; case TYPE_STORE_MULTIPLE : post_update_rtx_index = find_post_update_rtx ( insn ) ; if ( post_update_rtx_index != - 1 ) return SET_DEST ( parallel_element ( insn , post_update_rtx_index ) ) ; mem_rtx = SET_DEST ( parallel_element ( insn , 0 ) ) ; break ; case TYPE_LOAD : case TYPE_FLOAD : case TYPE_STORE : case TYPE_FSTORE : mem_rtx = extract_mem_rtx ( insn ) ; break ; default : gcc_unreachable ( ) ; } gcc_assert ( MEM_P ( mem_rtx ) ) ; if ( REG_P ( XEXP ( mem_rtx , 0 ) ) ) return XEXP ( mem_rtx , 0 ) ; if ( GET_CODE ( XEXP ( mem_rtx , 0 ) ) == LO_SUM ) return XEXP ( XEXP ( mem_rtx , 0 ) , 0 ) ; plus_rtx = XEXP ( mem_rtx , 0 ) ; if ( GET_CODE ( plus_rtx ) == SYMBOL_REF || GET_CODE ( plus_rtx ) == CONST ) return NULL_RTX ; gcc_assert ( GET_CODE ( plus_rtx ) == PLUS || GET_CODE ( plus_rtx ) == POST_INC || GET_CODE ( plus_rtx ) == POST_DEC || GET_CODE ( plus_rtx ) == POST_MODIFY ) ; if ( REG_P ( XEXP ( plus_rtx , 0 ) ) ) return XEXP ( plus_rtx , 0 ) ; gcc_assert ( REG_P ( XEXP ( plus_rtx , 1 ) ) ) ; return XEXP ( plus_rtx , 1 ) ; } </s>


<s> rtx extract_branch_condition_rtx ( rtx_insn * insn ) { gcc_assert ( CALL_P ( insn ) || JUMP_P ( insn ) ) ; rtx body = PATTERN ( insn ) ; if ( GET_CODE ( body ) == SET ) { rtx if_then_else_rtx = SET_SRC ( body ) ; if ( GET_CODE ( if_then_else_rtx ) == IF_THEN_ELSE ) return XEXP ( if_then_else_rtx , 0 ) ; return NULL_RTX ; } if ( GET_CODE ( body ) == COND_EXEC ) return XEXP ( body , 0 ) ; return NULL_RTX ; } </s>

Extract the rtx representing the branch condition to help recognize data hazards .


<s> rtx extract_branch_target_rtx ( rtx_insn * insn ) { gcc_assert ( CALL_P ( insn ) || JUMP_P ( insn ) ) ; rtx body = PATTERN ( insn ) ; if ( GET_CODE ( body ) == SET ) { if ( GET_CODE ( SET_SRC ( body ) ) == IF_THEN_ELSE ) return NULL_RTX ; return SET_SRC ( body ) ; } if ( GET_CODE ( body ) == CALL ) return XEXP ( body , 0 ) ; if ( GET_CODE ( body ) == PARALLEL ) { rtx first_rtx = parallel_element ( body , 0 ) ; if ( GET_CODE ( first_rtx ) == SET ) return SET_SRC ( first_rtx ) ; if ( GET_CODE ( first_rtx ) == CALL ) return XEXP ( first_rtx , 0 ) ; } if ( GET_CODE ( body ) == COND_EXEC ) { rtx addr_rtx = XEXP ( body , 1 ) ; if ( GET_CODE ( addr_rtx ) == SET ) return SET_SRC ( addr_rtx ) ; if ( GET_CODE ( addr_rtx ) == PARALLEL ) { rtx first_rtx = parallel_element ( addr_rtx , 0 ) ; if ( GET_CODE ( first_rtx ) == SET ) { rtx call_rtx = SET_SRC ( first_rtx ) ; gcc_assert ( GET_CODE ( call_rtx ) == CALL ) ; return XEXP ( call_rtx , 0 ) ; } if ( GET_CODE ( first_rtx ) == CALL ) return XEXP ( first_rtx , 0 ) ; } } gcc_unreachable ( ) ; } </s>

Extract the rtx representing the branch target to help recognize data hazards .


<s> rtx extract_mac_non_acc_rtx ( rtx_insn * insn ) { rtx exp = SET_SRC ( PATTERN ( insn ) ) ; switch ( get_attr_type ( insn ) ) { case TYPE_MAC : case TYPE_DMAC : if ( REG_P ( XEXP ( exp , 0 ) ) ) return XEXP ( exp , 1 ) ; else return XEXP ( exp , 0 ) ; default : gcc_unreachable ( ) ; } } </s>


<s> rtx extract_mem_rtx ( rtx_insn * insn ) { rtx body = PATTERN ( insn ) ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD : case TYPE_FLOAD : if ( MEM_P ( SET_SRC ( body ) ) ) return SET_SRC ( body ) ; if ( GET_CODE ( SET_SRC ( body ) ) == UNSPEC ) { gcc_assert ( MEM_P ( XVECEXP ( SET_SRC ( body ) , 0 , 0 ) ) ) ; return XVECEXP ( SET_SRC ( body ) , 0 , 0 ) ; } gcc_assert ( MEM_P ( XEXP ( SET_SRC ( body ) , 0 ) ) ) ; return XEXP ( SET_SRC ( body ) , 0 ) ; case TYPE_STORE : case TYPE_FSTORE : if ( MEM_P ( SET_DEST ( body ) ) ) return SET_DEST ( body ) ; if ( GET_CODE ( SET_DEST ( body ) ) == UNSPEC ) { gcc_assert ( MEM_P ( XVECEXP ( SET_DEST ( body ) , 0 , 0 ) ) ) ; return XVECEXP ( SET_DEST ( body ) , 0 , 0 ) ; } gcc_assert ( MEM_P ( XEXP ( SET_DEST ( body ) , 0 ) ) ) ; return XEXP ( SET_DEST ( body ) , 0 ) ; default : gcc_unreachable ( ) ; } } </s>

Extract the MEM rtx from a load/store insn .


<s> rtx extract_movd44_odd_reg ( rtx_insn * insn ) { gcc_assert ( movd44_insn_p ( insn ) ) ; rtx def_reg = SET_DEST ( PATTERN ( insn ) ) ; machine_mode mode ; gcc_assert ( REG_P ( def_reg ) || GET_CODE ( def_reg ) == SUBREG ) ; switch ( GET_MODE ( def_reg ) ) { case E_DImode : mode = SImode ; break ; case E_DFmode : mode = SFmode ; break ; default : gcc_unreachable ( ) ; } return gen_highpart ( mode , def_reg ) ; } </s>

Extract the second result ( odd reg ) of a movd44 insn .


<s> rtx extract_offset_rtx ( rtx_insn * insn ) { rtx mem_rtx ; rtx plus_rtx ; rtx offset_rtx ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD_MULTIPLE : case TYPE_STORE_MULTIPLE : return NULL_RTX ; case TYPE_LOAD : case TYPE_FLOAD : case TYPE_STORE : case TYPE_FSTORE : mem_rtx = extract_mem_rtx ( insn ) ; break ; default : gcc_unreachable ( ) ; } gcc_assert ( MEM_P ( mem_rtx ) ) ; if ( REG_P ( XEXP ( mem_rtx , 0 ) ) ) return NULL_RTX ; plus_rtx = XEXP ( mem_rtx , 0 ) ; switch ( GET_CODE ( plus_rtx ) ) { case SYMBOL_REF : case CONST : case POST_INC : case POST_DEC : return NULL_RTX ; case PLUS : if ( REG_P ( XEXP ( plus_rtx , 0 ) ) ) offset_rtx = XEXP ( plus_rtx , 1 ) ; else { gcc_assert ( REG_P ( XEXP ( plus_rtx , 1 ) ) ) ; offset_rtx = XEXP ( plus_rtx , 0 ) ; } if ( ARITHMETIC_P ( offset_rtx ) ) { gcc_assert ( GET_CODE ( offset_rtx ) == MULT ) ; gcc_assert ( REG_P ( XEXP ( offset_rtx , 0 ) ) ) ; offset_rtx = XEXP ( offset_rtx , 0 ) ; } break ; case LO_SUM : offset_rtx = XEXP ( plus_rtx , 1 ) ; break ; case POST_MODIFY : gcc_assert ( REG_P ( XEXP ( plus_rtx , 0 ) ) ) ; plus_rtx = XEXP ( plus_rtx , 1 ) ; gcc_assert ( GET_CODE ( plus_rtx ) == PLUS ) ; offset_rtx = XEXP ( plus_rtx , 0 ) ; break ; default : gcc_unreachable ( ) ; } return offset_rtx ; } </s>

Extract the offset rtx from load/store insns . The function returns NULL_RTX if offset is absent .


<s> rtx extract_pattern_from_insn ( rtx insn ) { if ( INSN_P ( insn ) ) return PATTERN ( insn ) ; return insn ; } </s>

Get the rtx in the PATTERN field of an insn . If INSN is not an insn , the funciton does n't change anything and returns it directly .


<s> rtx extract_shift_reg ( rtx alu_shift_rtx ) { alu_shift_rtx = extract_pattern_from_insn ( alu_shift_rtx ) ; rtx alu_rtx = SET_SRC ( alu_shift_rtx ) ; rtx shift_rtx ; if ( REG_P ( XEXP ( alu_rtx , 0 ) ) ) shift_rtx = XEXP ( alu_rtx , 1 ) ; else shift_rtx = XEXP ( alu_rtx , 0 ) ; return XEXP ( shift_rtx , 0 ) ; } </s>

Extract the register of the shift operand from an ALU_SHIFT rtx .


<s> int find_post_update_rtx ( rtx_insn * insn ) { rtx mem_rtx ; int i , len ; switch ( get_attr_type ( insn ) ) { case TYPE_LOAD_MULTIPLE : case TYPE_STORE_MULTIPLE : len = parallel_elements ( insn ) ; for ( i = 0 ; i < len ; ++ i ) { rtx curr_insn = parallel_element ( insn , i ) ; if ( GET_CODE ( curr_insn ) == SET && REG_P ( SET_DEST ( curr_insn ) ) && GET_CODE ( SET_SRC ( curr_insn ) ) == PLUS ) return i ; } return - 1 ; case TYPE_LOAD : case TYPE_FLOAD : case TYPE_STORE : case TYPE_FSTORE : mem_rtx = extract_mem_rtx ( insn ) ; switch ( GET_CODE ( XEXP ( mem_rtx , 0 ) ) ) { case POST_INC : case POST_DEC : case POST_MODIFY : return 0 ; default : return - 1 ; } default : gcc_unreachable ( ) ; } } </s>

Find the post update rtx in INSN . If INSN is a load/store multiple insn , the function returns the vector index of its parallel part . If INSN is a single load/store insn , the function returns 0 . If INSN is not a post- update insn , the function returns -1 .


<s> bool immed_offset_p ( rtx mem_rtx ) { gcc_assert ( MEM_P ( mem_rtx ) ) ; rtx addr_rtx = XEXP ( mem_rtx , 0 ) ; if ( REG_P ( addr_rtx ) ) return true ; if ( GET_CODE ( addr_rtx ) == PLUS && GET_CODE ( XEXP ( addr_rtx , 1 ) ) == CONST_INT ) return true ; return false ; } </s>

Check if the address of MEM_RTX consists of a base register and an immediate offset .


<s> bool load_single_p ( rtx_insn * insn ) { if ( get_attr_type ( insn ) != TYPE_LOAD ) return false ; if ( INSN_CODE ( insn ) == CODE_FOR_move_di || INSN_CODE ( insn ) == CODE_FOR_move_df ) return false ; return true ; } </s>

Functions to determine whether INSN is single-word , double-word or partial-word load/store insn .


<s> bool movd44_insn_p ( rtx_insn * insn ) { if ( get_attr_type ( insn ) == TYPE_ALU && ( INSN_CODE ( insn ) == CODE_FOR_move_di || INSN_CODE ( insn ) == CODE_FOR_move_df ) ) { rtx body = PATTERN ( insn ) ; gcc_assert ( GET_CODE ( body ) == SET ) ; rtx src = SET_SRC ( body ) ; rtx dest = SET_DEST ( body ) ; if ( ( REG_P ( src ) || GET_CODE ( src ) == SUBREG ) && ( REG_P ( dest ) || GET_CODE ( dest ) == SUBREG ) ) return true ; return false ; } return false ; } </s>


<s> rtx parallel_element ( rtx parallel_rtx , int nth ) { parallel_rtx = extract_pattern_from_insn ( parallel_rtx ) ; gcc_assert ( GET_CODE ( parallel_rtx ) == PARALLEL ) ; int len = parallel_elements ( parallel_rtx ) ; if ( nth >= 0 ) { if ( nth >= len ) return NULL_RTX ; return XVECEXP ( parallel_rtx , 0 , nth ) ; } else { if ( len + nth < 0 ) return NULL_RTX ; return XVECEXP ( parallel_rtx , 0 , len + nth ) ; } } </s>

Extract an rtx from a parallel rtx with index NTH . If NTH is a negative value , the function returns the last NTH rtx .


<s> size_t parallel_elements ( rtx parallel_rtx ) { parallel_rtx = extract_pattern_from_insn ( parallel_rtx ) ; gcc_assert ( GET_CODE ( parallel_rtx ) == PARALLEL ) ; return XVECLEN ( parallel_rtx , 0 ) ; } </s>

Get the number of elements in a parallel rtx .


<s> bool post_update_insn_p ( rtx_insn * insn ) { if ( find_post_update_rtx ( insn ) == - 1 ) return false ; else return true ; } </s>

Determine if INSN is a post update insn .


<s> unsigned int nds32_debugger_regno ( unsigned int regno ) { if ( NDS32_IS_FPR_REGNUM ( regno ) ) return regno + 4 ; return regno ; } </s>

Map internal gcc register numbers to DWARF2 register numbers .


<s> static rtx_insn * nds32_md_asm_adjust ( vec < rtx > & outputs ATTRIBUTE_UNUSED , vec < rtx > & inputs ATTRIBUTE_UNUSED , vec < machine_mode > & input_modes ATTRIBUTE_UNUSED , vec < const char * > & constraints ATTRIBUTE_UNUSED , vec < rtx > & clobbers , HARD_REG_SET & clobbered_regs ) { if ( ! flag_inline_asm_r15 ) { clobbers . safe_push ( gen_rtx_REG ( SImode , TA_REGNUM ) ) ; SET_HARD_REG_BIT ( clobbered_regs , TA_REGNUM ) ; } return NULL ; } </s>


<s> static void nds32_setup_incoming_varargs ( cumulative_args_t ca , const function_arg_info & arg , int * pretend_args_size , int second_time ATTRIBUTE_UNUSED ) { unsigned int total_args_regs ; unsigned int num_of_used_regs ; unsigned int remaining_reg_count ; CUMULATIVE_ARGS * cum ; if ( TARGET_HARD_FLOAT ) return ; cum = get_cumulative_args ( ca ) ; total_args_regs = NDS32_MAX_GPR_REGS_FOR_ARGS + NDS32_GPR_ARG_FIRST_REGNUM ; if ( ! TYPE_NO_NAMED_ARGS_STDARG_P ( TREE_TYPE ( current_function_decl ) ) ) num_of_used_regs = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG ( cum -> gpr_offset , arg . mode , arg . type ) + NDS32_NEED_N_REGS_FOR_ARG ( arg . mode , arg . type ) ; else num_of_used_regs = cum -> gpr_offset + NDS32_GPR_ARG_FIRST_REGNUM ; remaining_reg_count = total_args_regs - num_of_used_regs ; * pretend_args_size = remaining_reg_count * UNITS_PER_WORD ; return ; } </s>


<s> int nds32_adjust_insn_length ( rtx_insn * insn , int length ) { rtx src , dst ; switch ( recog_memoized ( insn ) ) { case CODE_FOR_move_df : case CODE_FOR_move_di : src = XEXP ( PATTERN ( insn ) , 1 ) ; dst = XEXP ( PATTERN ( insn ) , 0 ) ; if ( REG_P ( src ) && REG_P ( dst ) && ( REGNO ( src ) % 2 ) == 0 && ( REGNO ( dst ) % 2 ) == 0 ) length = 2 ; break ; default : break ; } return length ; } </s>

Computing the Length of an Insn . Modifies the length assigned to instruction INSN . LEN is the initially computed length of the insn .


Before rtl epilogue has been expanded , this function is used .


"initialize $fp near to $gp location.\n"

"\t! If linker fails to use fp-as-gp transformation,\n"

After rtl prologue has been expanded , this function is used .


<s>
static
void
nds32_asm_function_epilogue
(
FILE
*
file
,
HOST_WIDE_INT
size
ATTRIBUTE_UNUSED
)
{
fprintf
(
file
,
"\t! END EPILOGUE\n"
)
;
}
</s>

The content produced from this function will be placed after epilogue body .


<s>
static
void
nds32_asm_function_prologue
(
FILE
*
file
,
HOST_WIDE_INT
size
ATTRIBUTE_UNUSED
)
{
int
r
;
const
char
*
func_name
;
tree
attrs
;
tree
name
;
fprintf
(
file
,
"\t! BEGIN PROLOGUE\n"
)
;
fprintf
(
file
,
"\t!     fp needed: %d\n"
,
frame_pointer_needed
)
;
fprintf
(
file
,
"\t!  pretend_args: %d\n"
,
cfun
->
machine
->
va_args_size
)
;
fprintf
(
file
,
"\t!    local_size: %d\n"
,
cfun
->
machine
->
local_size
)
;
fprintf
(
file
,
"\t! out_args_size: %d\n"
,
cfun
->
machine
->
out_args_size
)
;
fprintf
(
file
,
"\t! registers ever_live: "
)
;
for
(
r
=
0
;
r
<
32
;
r
++
)
{
if
(
df_regs_ever_live_p
(
r
)
)
fprintf
(
file
,
"%s, "
,
reg_names
[
r
]
)
;
}
fputc
(
'\n'
,
file
)
;
fprintf
(
file
,
"\t! function attributes: "
)
;
attrs
=
DECL_ATTRIBUTES
(
current_function_decl
)
;
if
(
!
attrs
)
fprintf
(
file
,
"None"
)
;
func_name
=
IDENTIFIER_POINTER
(
DECL_NAME
(
current_function_decl
)
)
;
nds32_construct_isr_vectors_information
(
attrs
,
func_name
)
;
while
(
attrs
)
{
name
=
TREE_PURPOSE
(
attrs
)
;
fprintf
(
file
,
"%s "
,
IDENTIFIER_POINTER
(
name
)
)
;
attrs
=
TREE_CHAIN
(
attrs
)
;
}
fputc
(
'\n'
,
file
)
;
}
</s>

The content produced from this function will be placed before prologue body .

nds32
"\t! BEGIN PROLOGUE\n"
"\t!     fp needed: %d\n"
"\t!  pretend_args: %d\n"
"\t!    local_size: %d\n"
"\t! out_args_size: %d\n"
"\t! registers ever_live: "
0
32
"%s, "
"\t! function attributes: "
"None"
"%s "


<s> int nds32_can_use_return_insn ( void ) { if ( ! reload_completed ) return 0 ; return ( cfun -> machine -> naked_p && ( cfun -> machine -> va_args_size == 0 ) ) ; } </s>

Return nonzero if this function is known to have a null epilogue . This allows the optimizer to omit jumps to jumps if no stack was created .


<s> static void nds32_emit_stack_v3pop ( rtx Rb , rtx Re , rtx En4 ATTRIBUTE_UNUSED , rtx imm8u ) { int regno ; int num_use_regs ; int par_index ; int offset ; rtx reg ; rtx mem ; rtx pop_rtx ; rtx adjust_sp_rtx ; rtx parallel_insn ; rtx dwarf = NULL_RTX ; num_use_regs = REGNO ( Re ) - REGNO ( Rb ) + 1 + 3 ; parallel_insn = gen_rtx_PARALLEL ( VOIDmode , rtvec_alloc ( num_use_regs + 1 ) ) ; par_index = 0 ; offset = 0 ; for ( regno = REGNO ( Rb ) ; regno <= ( int ) REGNO ( Re ) ; regno ++ ) { reg = gen_rtx_REG ( SImode , regno ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; pop_rtx = gen_rtx_SET ( VOIDmode , reg , mem ) ; XVECEXP ( parallel_insn , 0 , par_index ) = pop_rtx ; RTX_FRAME_RELATED_P ( pop_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; } reg = gen_rtx_REG ( SImode , FP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; pop_rtx = gen_rtx_SET ( VOIDmode , reg , mem ) ; XVECEXP ( parallel_insn , 0 , par_index ) = pop_rtx ; RTX_FRAME_RELATED_P ( pop_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; reg = gen_rtx_REG ( SImode , GP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; pop_rtx = gen_rtx_SET ( VOIDmode , reg , mem ) ; XVECEXP ( parallel_insn , 0 , par_index ) = pop_rtx ; RTX_FRAME_RELATED_P ( pop_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; reg = gen_rtx_REG ( SImode , LP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; pop_rtx = gen_rtx_SET ( VOIDmode , reg , mem ) ; XVECEXP ( parallel_insn , 0 , par_index ) = pop_rtx ; RTX_FRAME_RELATED_P ( pop_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; adjust_sp_rtx = gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , offset + INTVAL ( imm8u ) ) ) ; XVECEXP ( parallel_insn , 0 , par_index ) = adjust_sp_rtx ; dwarf = alloc_reg_note ( REG_CFA_ADJUST_CFA , copy_rtx ( adjust_sp_rtx ) , dwarf ) ; parallel_insn = emit_insn ( parallel_insn ) ; RTX_FRAME_RELATED_P ( parallel_insn ) = 1 ; REG_NOTES ( parallel_insn ) = dwarf ; } </s>

Function to create a parallel rtx pattern which presents stack v3pop behavior . The overall concept are : `` pop registers from memory '' , `` adjust stack pointer '' .


<s> static void nds32_emit_stack_v3push ( rtx Rb , rtx Re , rtx En4 ATTRIBUTE_UNUSED , rtx imm8u ) { int regno ; int num_use_regs ; int par_index ; int offset ; rtx reg ; rtx mem ; rtx push_rtx ; rtx adjust_sp_rtx ; rtx parallel_insn ; num_use_regs = REGNO ( Re ) - REGNO ( Rb ) + 1 + 3 ; parallel_insn = gen_rtx_PARALLEL ( VOIDmode , rtvec_alloc ( num_use_regs + 1 ) ) ; par_index = 0 ; offset = - ( num_use_regs * 4 ) ; for ( regno = REGNO ( Rb ) ; regno <= ( int ) REGNO ( Re ) ; regno ++ ) { reg = gen_rtx_REG ( SImode , regno ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( VOIDmode , mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; } reg = gen_rtx_REG ( SImode , FP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( VOIDmode , mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; reg = gen_rtx_REG ( SImode , GP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( VOIDmode , mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; reg = gen_rtx_REG ( SImode , LP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( VOIDmode , mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; offset = - ( num_use_regs * 4 ) ; adjust_sp_rtx = gen_rtx_SET ( VOIDmode , stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , offset - INTVAL ( imm8u ) ) ) ; XVECEXP ( parallel_insn , 0 , par_index ) = adjust_sp_rtx ; RTX_FRAME_RELATED_P ( adjust_sp_rtx ) = 1 ; parallel_insn = emit_insn ( parallel_insn ) ; RTX_FRAME_RELATED_P ( parallel_insn ) = 1 ; } </s>

Function to create a parallel rtx pattern which presents stack v3push behavior . The overall concept are : `` push registers to memory '' , `` adjust stack pointer '' .


<s> void nds32_expand_epilogue ( bool sibcall_p ) { int sp_adjust ; int en4_const ; rtx Rb , Re ; rtx sp_adjust_insn ; nds32_compute_stack_frame ( ) ; emit_insn ( gen_blockage ( ) ) ; if ( cfun -> machine -> naked_p ) { if ( cfun -> machine -> va_args_size != 0 ) { sp_adjust = cfun -> machine -> va_args_size + cfun -> machine -> va_args_area_padding_bytes ; sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; RTX_FRAME_RELATED_P ( sp_adjust_insn ) = 1 ; } if ( ! sibcall_p ) emit_jump_insn ( gen_return_internal ( ) ) ; return ; } if ( frame_pointer_needed ) { sp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size ; sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , hard_frame_pointer_rtx , GEN_INT ( - 1 * sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; RTX_FRAME_RELATED_P ( sp_adjust_insn ) = 1 ; } else { sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes ; sp_adjust = nds32_force_addi_stack_int ( sp_adjust ) ; if ( sp_adjust ) { sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; RTX_FRAME_RELATED_P ( sp_adjust_insn ) = 1 ; } } Rb = gen_rtx_REG ( SImode , cfun -> machine -> callee_saved_first_gpr_regno ) ; Re = gen_rtx_REG ( SImode , cfun -> machine -> callee_saved_last_gpr_regno ) ; en4_const = 0 ; if ( cfun -> machine -> fp_size ) en4_const += 8 ; if ( cfun -> machine -> gp_size ) en4_const += 4 ; if ( cfun -> machine -> lp_size ) en4_const += 2 ; if ( ! ( REGNO ( Rb ) == SP_REGNUM && REGNO ( Re ) == SP_REGNUM && en4_const == 0 ) ) { nds32_emit_stack_pop_multiple ( Rb , Re , GEN_INT ( en4_const ) ) ; } if ( cfun -> machine -> va_args_size != 0 ) { sp_adjust = cfun -> machine -> va_args_size + cfun -> machine -> va_args_area_padding_bytes ; sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; RTX_FRAME_RELATED_P ( sp_adjust_insn ) = 1 ; } if ( ! sibcall_p ) emit_jump_insn ( gen_return_internal ( ) ) ; } </s>

Function for normal multiple pop epilogue .


<s> void nds32_expand_epilogue_v3pop ( bool sibcall_p ) { int sp_adjust ; rtx Rb , Re ; rtx sp_adjust_insn ; nds32_compute_stack_frame ( ) ; emit_insn ( gen_blockage ( ) ) ; if ( cfun -> machine -> naked_p ) { if ( ! sibcall_p ) emit_jump_insn ( gen_return_internal ( ) ) ; return ; } Rb = gen_rtx_REG ( SImode , cfun -> machine -> callee_saved_first_gpr_regno ) ; Re = gen_rtx_REG ( SImode , cfun -> machine -> callee_saved_last_gpr_regno ) ; sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes ; if ( satisfies_constraint_Iu08 ( GEN_INT ( sp_adjust ) ) && NDS32_DOUBLE_WORD_ALIGN_P ( sp_adjust ) && ! cfun -> calls_alloca ) { nds32_emit_stack_v3pop ( Rb , Re , GEN_INT ( 14 ) , GEN_INT ( sp_adjust ) ) ; } else { if ( frame_pointer_needed ) { sp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size ; sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , hard_frame_pointer_rtx , GEN_INT ( - 1 * sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; } else { sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes ; sp_adjust = nds32_force_addi_stack_int ( sp_adjust ) ; if ( sp_adjust ) { sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; } } nds32_emit_stack_v3pop ( Rb , Re , GEN_INT ( 14 ) , GEN_INT ( 0 ) ) ; } emit_jump_insn ( gen_pop25return ( ) ) ; } </s>


<s> void nds32_expand_prologue ( void ) { int fp_adjust ; int sp_adjust ; int en4_const ; rtx Rb , Re ; rtx fp_adjust_insn , sp_adjust_insn ; nds32_compute_stack_frame ( ) ; if ( cfun -> machine -> va_args_size != 0 ) { Rb = gen_rtx_REG ( SImode , cfun -> machine -> va_args_first_regno ) ; Re = gen_rtx_REG ( SImode , cfun -> machine -> va_args_last_regno ) ; nds32_emit_stack_push_multiple ( Rb , Re , GEN_INT ( 0 ) , true ) ; if ( cfun -> machine -> va_args_area_padding_bytes ) { sp_adjust = cfun -> machine -> va_args_area_padding_bytes ; sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - 1 * sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; RTX_FRAME_RELATED_P ( sp_adjust_insn ) = 1 ; } } if ( cfun -> machine -> naked_p ) return ; Rb = gen_rtx_REG ( SImode , cfun -> machine -> callee_saved_first_gpr_regno ) ; Re = gen_rtx_REG ( SImode , cfun -> machine -> callee_saved_last_gpr_regno ) ; en4_const = 0 ; if ( cfun -> machine -> fp_size ) en4_const += 8 ; if ( cfun -> machine -> gp_size ) en4_const += 4 ; if ( cfun -> machine -> lp_size ) en4_const += 2 ; if ( ! ( REGNO ( Rb ) == SP_REGNUM && REGNO ( Re ) == SP_REGNUM && en4_const == 0 ) ) { nds32_emit_stack_push_multiple ( Rb , Re , GEN_INT ( en4_const ) , false ) ; } if ( frame_pointer_needed ) { fp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size ; fp_adjust_insn = gen_addsi3 ( hard_frame_pointer_rtx , stack_pointer_rtx , GEN_INT ( fp_adjust ) ) ; fp_adjust_insn = emit_insn ( fp_adjust_insn ) ; RTX_FRAME_RELATED_P ( fp_adjust_insn ) = 1 ; } sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes ; sp_adjust = nds32_force_addi_stack_int ( ( - 1 ) * sp_adjust ) ; if ( sp_adjust ) { sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - 1 * sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; RTX_FRAME_RELATED_P ( sp_adjust_insn ) = 1 ; } emit_insn ( gen_blockage ( ) ) ; } </s>

Function for normal multiple push prologue .


<s> void nds32_expand_prologue_v3push ( void ) { int fp_adjust ; int sp_adjust ; rtx Rb , Re ; rtx fp_adjust_insn , sp_adjust_insn ; nds32_compute_stack_frame ( ) ; if ( cfun -> machine -> naked_p ) return ; Rb = gen_rtx_REG ( SImode , cfun -> machine -> callee_saved_first_gpr_regno ) ; Re = gen_rtx_REG ( SImode , cfun -> machine -> callee_saved_last_gpr_regno ) ; sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes ; if ( satisfies_constraint_Iu08 ( GEN_INT ( sp_adjust ) ) && NDS32_DOUBLE_WORD_ALIGN_P ( sp_adjust ) ) { nds32_emit_stack_v3push ( Rb , Re , GEN_INT ( 14 ) , GEN_INT ( sp_adjust ) ) ; if ( frame_pointer_needed ) { fp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size + sp_adjust ; fp_adjust_insn = gen_addsi3 ( hard_frame_pointer_rtx , stack_pointer_rtx , GEN_INT ( fp_adjust ) ) ; fp_adjust_insn = emit_insn ( fp_adjust_insn ) ; } } else { nds32_emit_stack_v3push ( Rb , Re , GEN_INT ( 14 ) , GEN_INT ( 0 ) ) ; if ( frame_pointer_needed ) { fp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size ; fp_adjust_insn = gen_addsi3 ( hard_frame_pointer_rtx , stack_pointer_rtx , GEN_INT ( fp_adjust ) ) ; fp_adjust_insn = emit_insn ( fp_adjust_insn ) ; } sp_adjust = nds32_force_addi_stack_int ( ( - 1 ) * sp_adjust ) ; if ( sp_adjust ) { sp_adjust_insn = gen_addsi3 ( stack_pointer_rtx , stack_pointer_rtx , GEN_INT ( - 1 * sp_adjust ) ) ; sp_adjust_insn = emit_insn ( sp_adjust_insn ) ; RTX_FRAME_RELATED_P ( sp_adjust_insn ) = 1 ; } } emit_insn ( gen_blockage ( ) ) ; } </s>


Function that may creates more instructions for large value on adjusting stack pointer . In nds32 target , 'addi ' can be used for stack pointer adjustment in prologue/epilogue stage . However , sometimes there are too many local variables so that the adjustment value is not able to be fit in the 'addi ' instruction . One solution is to move value into a register and then use 'add ' instruction . In practice , we use TA_REGNUM ( $ r15 ) to accomplish this purpose . Also , we need to return zero for sp adjustment so that proglogue/epilogue knows there is no need to create 'addi ' instruction .


<s> int nds32_hard_regno_mode_ok ( int regno , machine_mode mode ) { if ( HARD_REGNO_NREGS ( regno , mode ) == 1 || ! ( ( regno ) & 1 ) ) return 1 ; return 0 ; } </s>


<s> static struct machine_function * nds32_init_machine_status ( void ) { struct machine_function * machine ; machine = ggc_cleared_alloc < machine_function > ( ) ; machine -> naked_p = 0 ; machine -> fp_as_gp_p = 0 ; return machine ; } </s>

Function to save and restore machine-specific function data .


"invalid id value for interrupt/exception attribute"

"invalid nmi function for reset attribute"

"invalid warm function for reset attribute"

Add some checking when inserting attributes .


<s> static bool nds32_legitimate_index_p ( machine_mode outer_mode , rtx index , bool strict ) { int regno ; rtx op0 ; rtx op1 ; switch ( GET_CODE ( index ) ) { case REG : regno = REGNO ( index ) ; if ( strict ) return REGNO_OK_FOR_INDEX_P ( regno ) ; else return true ; case CONST_INT : if ( GET_MODE_SIZE ( outer_mode ) == 1 ) { if ( ! satisfies_constraint_Is15 ( index ) ) return false ; return true ; } if ( GET_MODE_SIZE ( outer_mode ) == 2 && NDS32_HALF_WORD_ALIGN_P ( INTVAL ( index ) ) ) { if ( ! satisfies_constraint_Is16 ( index ) ) return false ; return true ; } if ( GET_MODE_SIZE ( outer_mode ) == 4 && NDS32_SINGLE_WORD_ALIGN_P ( INTVAL ( index ) ) ) { if ( ! satisfies_constraint_Is17 ( index ) ) return false ; return true ; } if ( GET_MODE_SIZE ( outer_mode ) == 8 && NDS32_SINGLE_WORD_ALIGN_P ( INTVAL ( index ) ) ) { if ( ! satisfies_constraint_Is17 ( gen_int_mode ( INTVAL ( index ) + 4 , SImode ) ) ) return false ; return true ; } return false ; case MULT : op0 = XEXP ( index , 0 ) ; op1 = XEXP ( index , 1 ) ; if ( REG_P ( op0 ) && CONST_INT_P ( op1 ) ) { int multiplier ; multiplier = INTVAL ( op1 ) ; if ( multiplier != 1 && multiplier != 2 && multiplier != 4 ) return false ; regno = REGNO ( op0 ) ; if ( strict ) return REGNO_OK_FOR_INDEX_P ( regno ) ; else return true ; } return false ; case ASHIFT : op0 = XEXP ( index , 0 ) ; op1 = XEXP ( index , 1 ) ; if ( REG_P ( op0 ) && CONST_INT_P ( op1 ) ) { int sv ; sv = INTVAL ( op1 ) ; if ( sv != 0 && sv != 1 && sv != 2 ) return false ; regno = REGNO ( op0 ) ; if ( strict ) return REGNO_OK_FOR_INDEX_P ( regno ) ; else return true ; } return false ; default : return false ; } } </s>

Function that check if 'INDEX ' is valid to be a index rtx for address . OUTER_MODE : Machine mode of outer address rtx . INDEX : Check if this rtx is valid to be a index for address . STRICT : If it is true , we are in reload pass or after reload pass .


<s> bool nds32_ls_333_p ( rtx rt , rtx ra , rtx imm , machine_mode mode ) { if ( REGNO_REG_CLASS ( REGNO ( rt ) ) == LOW_REGS && REGNO_REG_CLASS ( REGNO ( ra ) ) == LOW_REGS ) { if ( GET_MODE_SIZE ( mode ) == 4 ) return satisfies_constraint_Iu05 ( imm ) ; if ( GET_MODE_SIZE ( mode ) == 2 ) return satisfies_constraint_Iu04 ( imm ) ; if ( GET_MODE_SIZE ( mode ) == 1 ) return satisfies_constraint_Iu03 ( imm ) ; } return false ; } </s>

Function to test 333-form for load/store instructions . This is auxiliary extern function for auxiliary macro in nds32.h . Because it is a little complicated , we use function instead of macro .


<s> static bool nds32_naked_function_p ( tree func ) { tree t ; if ( TREE_CODE ( func ) != FUNCTION_DECL ) abort ( ) ; t = lookup_attribute ( "naked" , DECL_ATTRIBUTES ( func ) ) ; return ( t != NULL_TREE ) ; } </s>

Return true if FUNC is a naked function .


<s> static int nds32_register_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t from , reg_class_t to ) { if ( from == HIGH_REGS || to == HIGH_REGS ) return 6 ; return 2 ; } </s>

Describing Relative Costs of Operations .


<s> enum reg_class nds32_regno_reg_class ( int regno ) { if ( regno >= 0 && regno <= 7 ) return LOW_REGS ; else if ( regno >= 8 && regno <= 11 ) return MIDDLE_REGS ; else if ( regno >= 12 && regno <= 14 ) return HIGH_REGS ; else if ( regno == 15 ) return R15_TA_REG ; else if ( regno >= 16 && regno <= 19 ) return MIDDLE_REGS ; else if ( regno >= 20 && regno <= 31 ) return HIGH_REGS ; else if ( regno == 32 || regno == 33 ) return FRAME_REGS ; else return NO_REGS ; } </s>


<s> static bool nds32_rtx_costs ( rtx x , int code , int outer_code , int opno , int * total , bool speed ) { return nds32_rtx_costs_impl ( x , code , outer_code , opno , total , speed ) ; } </s>

This target hook describes the relative costs of RTL expressions . Return 'true ' when all subexpressions of x have been processed . Return 'false ' to sum the costs of sub-rtx , plus cost of this operation . Refer to gcc/rtlanal.cc for more information .


<s> static void nds32_setup_incoming_varargs ( cumulative_args_t ca , machine_mode mode , tree type , int * pretend_args_size , int second_time ATTRIBUTE_UNUSED ) { unsigned int total_args_regs ; unsigned int num_of_used_regs ; unsigned int remaining_reg_count ; CUMULATIVE_ARGS * cum ; if ( TARGET_HARD_FLOAT ) return ; cum = get_cumulative_args ( ca ) ; total_args_regs = NDS32_MAX_GPR_REGS_FOR_ARGS + NDS32_GPR_ARG_FIRST_REGNUM ; num_of_used_regs = NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG ( cum -> gpr_offset , mode , type ) + NDS32_NEED_N_REGS_FOR_ARG ( mode , type ) ; remaining_reg_count = total_args_regs - num_of_used_regs ; * pretend_args_size = remaining_reg_count * UNITS_PER_WORD ; return ; } </s>


<s> int nds32_target_alignment ( rtx label ) { rtx_insn * insn ; if ( optimize_size ) return 0 ; insn = next_active_insn ( label ) ; if ( insn == 0 ) return 0 ; else if ( ( get_attr_length ( insn ) % 4 ) == 0 ) return 2 ; else return 0 ; } </s>

Return align 2 ( log base 2 ) if the next instruction of LABEL is 4 byte .


<s> static void nds32_emit_stack_v3pop ( rtx Rb , rtx Re , rtx En4 ATTRIBUTE_UNUSED , rtx imm8u ) { int regno ; int num_use_regs ; int par_index ; int offset ; rtx reg ; rtx mem ; rtx pop_rtx ; rtx adjust_sp_rtx ; rtx parallel_insn ; rtx dwarf = NULL_RTX ; num_use_regs = REGNO ( Re ) - REGNO ( Rb ) + 1 + 3 ; parallel_insn = gen_rtx_PARALLEL ( VOIDmode , rtvec_alloc ( num_use_regs + 1 ) ) ; par_index = 0 ; offset = 0 ; for ( regno = REGNO ( Rb ) ; regno <= ( int ) REGNO ( Re ) ; regno ++ ) { reg = gen_rtx_REG ( SImode , regno ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; pop_rtx = gen_rtx_SET ( reg , mem ) ; XVECEXP ( parallel_insn , 0 , par_index ) = pop_rtx ; RTX_FRAME_RELATED_P ( pop_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; } reg = gen_rtx_REG ( SImode , FP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; pop_rtx = gen_rtx_SET ( reg , mem ) ; XVECEXP ( parallel_insn , 0 , par_index ) = pop_rtx ; RTX_FRAME_RELATED_P ( pop_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; reg = gen_rtx_REG ( SImode , GP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; pop_rtx = gen_rtx_SET ( reg , mem ) ; XVECEXP ( parallel_insn , 0 , par_index ) = pop_rtx ; RTX_FRAME_RELATED_P ( pop_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; reg = gen_rtx_REG ( SImode , LP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; pop_rtx = gen_rtx_SET ( reg , mem ) ; XVECEXP ( parallel_insn , 0 , par_index ) = pop_rtx ; RTX_FRAME_RELATED_P ( pop_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; dwarf = alloc_reg_note ( REG_CFA_RESTORE , reg , dwarf ) ; adjust_sp_rtx = gen_rtx_SET ( stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , offset + INTVAL ( imm8u ) ) ) ; XVECEXP ( parallel_insn , 0 , par_index ) = adjust_sp_rtx ; dwarf = alloc_reg_note ( REG_CFA_ADJUST_CFA , copy_rtx ( adjust_sp_rtx ) , dwarf ) ; parallel_insn = emit_insn ( parallel_insn ) ; RTX_FRAME_RELATED_P ( parallel_insn ) = 1 ; REG_NOTES ( parallel_insn ) = dwarf ; } </s>


<s> static void nds32_emit_stack_v3push ( rtx Rb , rtx Re , rtx En4 ATTRIBUTE_UNUSED , rtx imm8u ) { int regno ; int num_use_regs ; int par_index ; int offset ; rtx reg ; rtx mem ; rtx push_rtx ; rtx adjust_sp_rtx ; rtx parallel_insn ; num_use_regs = REGNO ( Re ) - REGNO ( Rb ) + 1 + 3 ; parallel_insn = gen_rtx_PARALLEL ( VOIDmode , rtvec_alloc ( num_use_regs + 1 ) ) ; par_index = 0 ; offset = - ( num_use_regs * 4 ) ; for ( regno = REGNO ( Rb ) ; regno <= ( int ) REGNO ( Re ) ; regno ++ ) { reg = gen_rtx_REG ( SImode , regno ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; } reg = gen_rtx_REG ( SImode , FP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; reg = gen_rtx_REG ( SImode , GP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; reg = gen_rtx_REG ( SImode , LP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; offset = - ( num_use_regs * 4 ) ; adjust_sp_rtx = gen_rtx_SET ( stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , offset - INTVAL ( imm8u ) ) ) ; XVECEXP ( parallel_insn , 0 , par_index ) = adjust_sp_rtx ; RTX_FRAME_RELATED_P ( adjust_sp_rtx ) = 1 ; parallel_insn = emit_insn ( parallel_insn ) ; RTX_FRAME_RELATED_P ( parallel_insn ) = 1 ; } </s>


<s> int nds32_target_alignment ( rtx_insn * label ) { rtx_insn * insn ; if ( optimize_size ) return 0 ; insn = next_active_insn ( label ) ; if ( insn == 0 ) return 0 ; else if ( ( get_attr_length ( insn ) % 4 ) == 0 ) return 2 ; else return 0 ; } </s>


<s> int nds32_can_use_return_insn ( void ) { int sp_adjust ; if ( ! reload_completed ) return 0 ; sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; if ( ! cfun -> machine -> fp_as_gp_p && satisfies_constraint_Iu08 ( GEN_INT ( sp_adjust ) ) && NDS32_DOUBLE_WORD_ALIGN_P ( sp_adjust ) && ! cfun -> calls_alloca && NDS32_V3PUSH_AVAILABLE_P && ! ( TARGET_HARD_FLOAT && ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) ) ) return 1 ; return ( cfun -> machine -> naked_p && ( cfun -> machine -> va_args_size == 0 ) ) ; } </s>


<s> static void nds32_conditional_register_usage ( void ) { int regno ; if ( TARGET_HARD_FLOAT ) { for ( regno = NDS32_FIRST_FPR_REGNUM ; regno <= NDS32_LAST_FPR_REGNUM ; regno ++ ) { fixed_regs [ regno ] = 0 ; if ( regno < NDS32_FIRST_FPR_REGNUM + NDS32_MAX_FPR_REGS_FOR_ARGS ) call_used_regs [ regno ] = 1 ; else if ( regno >= NDS32_FIRST_FPR_REGNUM + 22 && regno < NDS32_FIRST_FPR_REGNUM + 48 ) call_used_regs [ regno ] = 1 ; else call_used_regs [ regno ] = 0 ; } } else if ( TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE ) { for ( regno = NDS32_FIRST_FPR_REGNUM ; regno <= NDS32_LAST_FPR_REGNUM ; regno ++ ) fixed_regs [ regno ] = 0 ; } } </s>


<s> void nds32_cpu_cpp_builtins ( struct cpp_reader * pfile ) { builtin_define ( "__nds32__" ) ; builtin_define ( "__NDS32__" ) ; if ( TARGET_HARD_FLOAT ) builtin_define ( "__NDS32_ABI_2FP_PLUS__" ) ; else builtin_define ( "__NDS32_ABI_2__" ) ; if ( TARGET_ISA_V2 ) builtin_define ( "__NDS32_ISA_V2__" ) ; if ( TARGET_ISA_V3 ) builtin_define ( "__NDS32_ISA_V3__" ) ; if ( TARGET_ISA_V3M ) builtin_define ( "__NDS32_ISA_V3M__" ) ; if ( TARGET_FPU_SINGLE ) builtin_define ( "__NDS32_EXT_FPU_SP__" ) ; if ( TARGET_FPU_DOUBLE ) builtin_define ( "__NDS32_EXT_FPU_DP__" ) ; if ( TARGET_EXT_FPU_FMA ) builtin_define ( "__NDS32_EXT_FPU_FMA__" ) ; if ( NDS32_EXT_FPU_DOT_E ) builtin_define ( "__NDS32_EXT_FPU_DOT_E__" ) ; if ( TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE ) { switch ( nds32_fp_regnum ) { case 0 : case 4 : builtin_define ( "__NDS32_EXT_FPU_CONFIG_0__" ) ; break ; case 1 : case 5 : builtin_define ( "__NDS32_EXT_FPU_CONFIG_1__" ) ; break ; case 2 : case 6 : builtin_define ( "__NDS32_EXT_FPU_CONFIG_2__" ) ; break ; case 3 : case 7 : builtin_define ( "__NDS32_EXT_FPU_CONFIG_3__" ) ; break ; default : abort ( ) ; } } if ( TARGET_BIG_ENDIAN ) builtin_define ( "__NDS32_EB__" ) ; else builtin_define ( "__NDS32_EL__" ) ; if ( TARGET_REDUCED_REGS ) builtin_define ( "__NDS32_REDUCED_REGS__" ) ; if ( TARGET_CMOV ) builtin_define ( "__NDS32_CMOV__" ) ; if ( TARGET_EXT_PERF ) builtin_define ( "__NDS32_EXT_PERF__" ) ; if ( TARGET_EXT_PERF2 ) builtin_define ( "__NDS32_EXT_PERF2__" ) ; if ( TARGET_EXT_STRING ) builtin_define ( "__NDS32_EXT_STRING__" ) ; if ( TARGET_16_BIT ) builtin_define ( "__NDS32_16_BIT__" ) ; if ( TARGET_GP_DIRECT ) builtin_define ( "__NDS32_GP_DIRECT__" ) ; if ( TARGET_VH ) builtin_define ( "__NDS32_VH__" ) ; if ( TARGET_BIG_ENDIAN ) builtin_define ( "__big_endian__" ) ; builtin_assert ( "cpu=nds32" ) ; builtin_assert ( "machine=nds32" ) ; if ( TARGET_HARD_FLOAT ) builtin_define ( "__NDS32_ABI_2FP_PLUS" ) ; else builtin_define ( "__NDS32_ABI_2" ) ; } </s>


<s> void nds32_expand_epilogue_v3pop ( bool sibcall_p ) { int sp_adjust ; unsigned Rb , Re ; nds32_compute_stack_frame ( ) ; emit_insn ( gen_blockage ( ) ) ; if ( cfun -> machine -> naked_p ) { if ( ! sibcall_p ) emit_jump_insn ( gen_return_internal ( ) ) ; return ; } Rb = cfun -> machine -> callee_saved_first_gpr_regno ; Re = cfun -> machine -> callee_saved_last_gpr_regno ; sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; if ( satisfies_constraint_Iu08 ( GEN_INT ( sp_adjust ) ) && NDS32_DOUBLE_WORD_ALIGN_P ( sp_adjust ) && ! cfun -> calls_alloca ) { if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { int fpr_position = cfun -> machine -> local_size + cfun -> machine -> out_args_size ; nds32_emit_v3pop_fpr_callee_saved ( fpr_position ) ; } nds32_emit_stack_v3pop ( Rb , Re , sp_adjust ) ; } else { if ( frame_pointer_needed ) { sp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size ; if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { sp_adjust = sp_adjust + cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; nds32_emit_adjust_frame ( stack_pointer_rtx , hard_frame_pointer_rtx , - 1 * sp_adjust ) ; nds32_emit_v3pop_fpr_callee_saved ( 0 ) ; } else { nds32_emit_adjust_frame ( stack_pointer_rtx , hard_frame_pointer_rtx , - 1 * sp_adjust ) ; } } else { sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { sp_adjust = sp_adjust - cfun -> machine -> callee_saved_area_gpr_padding_bytes - cfun -> machine -> callee_saved_fpr_regs_size ; nds32_emit_adjust_frame ( stack_pointer_rtx , stack_pointer_rtx , sp_adjust ) ; nds32_emit_v3pop_fpr_callee_saved ( 0 ) ; } else { nds32_emit_adjust_frame ( stack_pointer_rtx , stack_pointer_rtx , sp_adjust ) ; } } if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { int fpr_space = cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; nds32_emit_stack_v3pop ( Rb , Re , fpr_space ) ; } else { nds32_emit_stack_v3pop ( Rb , Re , 0 ) ; } } emit_jump_insn ( gen_pop25return ( ) ) ; } </s>


<s> void nds32_expand_prologue ( void ) { int fp_adjust ; int sp_adjust ; unsigned Rb , Re ; nds32_compute_stack_frame ( ) ; if ( cfun -> machine -> va_args_size != 0 ) { Rb = cfun -> machine -> va_args_first_regno ; Re = cfun -> machine -> va_args_last_regno ; nds32_emit_stack_push_multiple ( Rb , Re , false , false , false , true ) ; if ( cfun -> machine -> va_args_area_padding_bytes ) { sp_adjust = cfun -> machine -> va_args_area_padding_bytes ; nds32_emit_adjust_frame ( stack_pointer_rtx , stack_pointer_rtx , - 1 * sp_adjust ) ; } } if ( cfun -> machine -> naked_p ) return ; Rb = cfun -> machine -> callee_saved_first_gpr_regno ; Re = cfun -> machine -> callee_saved_last_gpr_regno ; if ( ! ( Rb == SP_REGNUM && Re == SP_REGNUM && cfun -> machine -> fp_size == 0 && cfun -> machine -> gp_size == 0 && cfun -> machine -> lp_size == 0 ) ) { nds32_emit_stack_push_multiple ( Rb , Re , cfun -> machine -> fp_size , cfun -> machine -> gp_size , cfun -> machine -> lp_size , false ) ; } if ( cfun -> machine -> use_eh_return_p ) { Rb = cfun -> machine -> eh_return_data_first_regno ; Re = cfun -> machine -> eh_return_data_last_regno ; nds32_emit_stack_push_multiple ( Rb , Re , false , false , false , false ) ; } if ( frame_pointer_needed ) { fp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size + cfun -> machine -> eh_return_data_regs_size ; nds32_emit_adjust_frame ( hard_frame_pointer_rtx , stack_pointer_rtx , fp_adjust ) ; } if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { int fpr_offset = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_fpr_regs_size ; if ( ! satisfies_constraint_Is14 ( GEN_INT ( fpr_offset ) ) ) { int fpr_space = cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; nds32_emit_adjust_frame ( stack_pointer_rtx , stack_pointer_rtx , - 1 * fpr_space ) ; nds32_emit_push_fpr_callee_saved ( 0 ) ; sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size ; nds32_emit_adjust_frame ( stack_pointer_rtx , stack_pointer_rtx , - 1 * sp_adjust ) ; } else { sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; nds32_emit_adjust_frame ( stack_pointer_rtx , stack_pointer_rtx , - 1 * sp_adjust ) ; int fpr_position = cfun -> machine -> out_args_size + cfun -> machine -> local_size ; nds32_emit_push_fpr_callee_saved ( fpr_position ) ; } } else { sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes ; nds32_emit_adjust_frame ( stack_pointer_rtx , stack_pointer_rtx , - 1 * sp_adjust ) ; } emit_insn ( gen_blockage ( ) ) ; } </s>


<s> void nds32_expand_prologue_v3push ( void ) { int fp_adjust ; int sp_adjust ; int fpr_space = 0 ; unsigned Rb , Re ; nds32_compute_stack_frame ( ) ; if ( cfun -> machine -> callee_saved_gpr_regs_size > 0 ) df_set_regs_ever_live ( FP_REGNUM , 1 ) ; if ( cfun -> machine -> naked_p ) return ; Rb = cfun -> machine -> callee_saved_first_gpr_regno ; Re = cfun -> machine -> callee_saved_last_gpr_regno ; sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; if ( satisfies_constraint_Iu08 ( GEN_INT ( sp_adjust ) ) && NDS32_DOUBLE_WORD_ALIGN_P ( sp_adjust ) ) { nds32_emit_stack_v3push ( Rb , Re , sp_adjust ) ; if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { int fpr_position = cfun -> machine -> local_size + cfun -> machine -> out_args_size ; nds32_emit_push_fpr_callee_saved ( fpr_position ) ; } if ( frame_pointer_needed ) { fp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size + sp_adjust ; nds32_emit_adjust_frame ( hard_frame_pointer_rtx , stack_pointer_rtx , fp_adjust ) ; } } else { if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { fpr_space = cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; nds32_emit_stack_v3push ( Rb , Re , fpr_space ) ; nds32_emit_push_fpr_callee_saved ( 0 ) ; } else { nds32_emit_stack_v3push ( Rb , Re , 0 ) ; } if ( frame_pointer_needed ) { fp_adjust = cfun -> machine -> fp_size + cfun -> machine -> gp_size + cfun -> machine -> lp_size + cfun -> machine -> callee_saved_gpr_regs_size ; if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { fp_adjust = fp_adjust + fpr_space ; } nds32_emit_adjust_frame ( hard_frame_pointer_rtx , stack_pointer_rtx , fp_adjust ) ; } if ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) { sp_adjust = sp_adjust - fpr_space ; } nds32_emit_adjust_frame ( stack_pointer_rtx , stack_pointer_rtx , - 1 * sp_adjust ) ; } emit_insn ( gen_blockage ( ) ) ; } </s>


<s> static bool nds32_function_ok_for_sibcall ( tree decl , tree exp ATTRIBUTE_UNUSED ) { return ( ! TARGET_V3PUSH && ( cfun -> machine -> va_args_size == 0 ) && decl ) ; } </s>

Return true if it is ok to do sibling call optimization .


<s> static bool nds32_hard_regno_mode_ok ( unsigned int regno , machine_mode mode ) { if ( regno > FIRST_PSEUDO_REGISTER ) return true ; if ( ( TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE ) && NDS32_IS_FPR_REGNUM ( regno ) ) { if ( NDS32_IS_EXT_FPR_REGNUM ( regno ) ) return ( NDS32_FPR_REGNO_OK_FOR_DOUBLE ( regno ) && ( mode == DFmode ) ) ; else if ( mode == SFmode || mode == SImode ) return NDS32_FPR_REGNO_OK_FOR_SINGLE ( regno ) ; else if ( mode == DFmode ) return NDS32_FPR_REGNO_OK_FOR_DOUBLE ( regno ) ; return false ; } if ( regno <= NDS32_LAST_GPR_REGNUM ) return ( targetm . hard_regno_nregs ( regno , mode ) == 1 || ! ( ( regno ) & 1 ) ) ; return false ; } </s>


<s> static struct machine_function * nds32_init_machine_status ( void ) { struct machine_function * machine ; machine = ggc_cleared_alloc < machine_function > ( ) ; machine -> use_eh_return_p = 0 ; machine -> naked_p = 0 ; machine -> fp_as_gp_p = 0 ; machine -> strict_aligned_p = 0 ; return machine ; } </s>


"invalid id value for interrupt/exception attribute"

"invalid nmi function for reset attribute"

"invalid warm function for reset attribute"


<s> static rtx_insn * nds32_md_asm_adjust ( vec < rtx > & outputs ATTRIBUTE_UNUSED , vec < rtx > & inputs ATTRIBUTE_UNUSED , vec < const char * > & constraints ATTRIBUTE_UNUSED , vec < rtx > & clobbers , HARD_REG_SET & clobbered_regs ) { clobbers . safe_push ( gen_rtx_REG ( SImode , TA_REGNUM ) ) ; SET_HARD_REG_BIT ( clobbered_regs , TA_REGNUM ) ; return NULL ; } </s>


<s> static int nds32_register_move_cost ( machine_mode mode ATTRIBUTE_UNUSED , reg_class_t from , reg_class_t to ) { if ( ( from == FP_REGS && to != FP_REGS ) || ( from != FP_REGS && to == FP_REGS ) ) return 9 ; else if ( from == HIGH_REGS || to == HIGH_REGS ) return optimize_size ? 6 : 2 ; else return 2 ; } </s>


<s> static void nds32_register_passes ( void ) { nds32_register_pass ( make_pass_nds32_relax_opt , PASS_POS_INSERT_AFTER , "mach" ) ; } </s>

This function is called from nds32_option_override ( ) . All new passes should be registered here .


<s> static bool nds32_address_register_rtx_p ( rtx x , bool strict ) { int regno ; if ( GET_CODE ( x ) != REG ) return false ; regno = REGNO ( x ) ; if ( strict ) return REGNO_OK_FOR_BASE_P ( regno ) ; else return true ; } </s>

Function that check if ' X ' is a valid address register . The variable 'STRICT ' is very important to make decision for register number . STRICT : true = > We are in reload pass or after reload pass . The register number should be strictly limited in general registers . STRICT : false = > Before reload pass , we are free to use any register number .


<s> int nds32_adjust_insn_length ( rtx_insn * insn , int length ) { int adjust_value = 0 ; switch ( recog_memoized ( insn ) ) { case CODE_FOR_call_internal : case CODE_FOR_call_value_internal : { if ( NDS32_ALIGN_P ( ) ) { rtx_insn * next_insn = next_active_insn ( insn ) ; if ( next_insn && get_attr_length ( next_insn ) != 2 ) adjust_value += 2 ; } if ( find_reg_note ( insn , REG_NORETURN , NULL_RTX ) ) { if ( TARGET_16_BIT ) adjust_value += 2 ; else adjust_value += 4 ; } } return length + adjust_value ; default : return length ; } } </s>

Computing the Length of an Insn . Modifies the length assigned to instruction INSN . LEN is the initially computed length of the insn .


<s>
static
void
nds32_asm_function_begin_epilogue
(
FILE
*
file
)
{
fprintf
(
file
,
"\t! BEGIN EPILOGUE\n"
)
;
}
</s>

Before rtl epilogue has been expanded , this function is used .


<s>
static
void
nds32_asm_function_end_prologue
(
FILE
*
file
)
{
fprintf
(
file
,
"\t! END PROLOGUE\n"
)
;
}
</s>

After rtl prologue has been expanded , this function is used .


<s>
static
void
nds32_asm_function_epilogue
(
FILE
*
file
)
{
fprintf
(
file
,
"\t! END EPILOGUE\n"
)
;
}
</s>

The content produced from this function will be placed after epilogue body .


<s>
static
void
nds32_asm_function_prologue
(
FILE
*
file
)
{
int
r
;
const
char
*
func_name
;
tree
attrs
;
tree
name
;
fprintf
(
file
,
"\t! BEGIN PROLOGUE\n"
)
;
fprintf
(
file
,
"\t!     fp needed: %d\n"
,
frame_pointer_needed
)
;
fprintf
(
file
,
"\t!  pretend_args: %d\n"
,
cfun
->
machine
->
va_args_size
)
;
fprintf
(
file
,
"\t!    local_size: %d\n"
,
cfun
->
machine
->
local_size
)
;
fprintf
(
file
,
"\t! out_args_size: %d\n"
,
cfun
->
machine
->
out_args_size
)
;
fprintf
(
file
,
"\t! registers ever_live: "
)
;
for
(
r
=
0
;
r
<
65
;
r
++
)
{
if
(
df_regs_ever_live_p
(
r
)
)
fprintf
(
file
,
"%s, "
,
reg_names
[
r
]
)
;
}
fputc
(
'\n'
,
file
)
;
fprintf
(
file
,
"\t! function attributes: "
)
;
attrs
=
DECL_ATTRIBUTES
(
current_function_decl
)
;
if
(
!
attrs
)
fprintf
(
file
,
"None"
)
;
func_name
=
IDENTIFIER_POINTER
(
DECL_NAME
(
current_function_decl
)
)
;
nds32_construct_isr_vectors_information
(
attrs
,
func_name
)
;
while
(
attrs
)
{
name
=
TREE_PURPOSE
(
attrs
)
;
fprintf
(
file
,
"%s "
,
IDENTIFIER_POINTER
(
name
)
)
;
attrs
=
TREE_CHAIN
(
attrs
)
;
}
fputc
(
'\n'
,
file
)
;
}
</s>

The content produced from this function will be placed before prologue body .

nds32
"\t! BEGIN PROLOGUE\n"
"\t!     fp needed: %d\n"
"\t!  pretend_args: %d\n"
"\t!    local_size: %d\n"
"\t! out_args_size: %d\n"
"\t! registers ever_live: "
0
65
"%s, "
"\t! function attributes: "
"None"
"%s "


"a nested function is not supported for reduced registers"

"\t! This code fragment will be copied "

"\t! space for saving nested function address\n"


<s> int nds32_can_use_return_insn ( void ) { int sp_adjust ; if ( ! reload_completed ) return 0 ; if ( cfun -> machine -> attr_naked_p && ! flag_ret_in_naked_func ) return 0 ; sp_adjust = cfun -> machine -> local_size + cfun -> machine -> out_args_size + cfun -> machine -> callee_saved_area_gpr_padding_bytes + cfun -> machine -> callee_saved_fpr_regs_size ; if ( ! cfun -> machine -> fp_as_gp_p && satisfies_constraint_Iu08 ( GEN_INT ( sp_adjust ) ) && NDS32_DOUBLE_WORD_ALIGN_P ( sp_adjust ) && ! cfun -> calls_alloca && NDS32_V3PUSH_AVAILABLE_P && ! ( TARGET_HARD_FLOAT && ( cfun -> machine -> callee_saved_first_fpr_regno != SP_REGNUM ) ) ) return 1 ; return ( cfun -> machine -> naked_p && ( cfun -> machine -> va_args_size == 0 ) ) ; } </s>

Return nonzero if this function is known to have a null epilogue . This allows the optimizer to omit jumps to jumps if no stack was created .


<s> static unsigned char nds32_class_max_nregs ( reg_class_t rclass ATTRIBUTE_UNUSED , machine_mode mode ) { return ( ( GET_MODE_SIZE ( mode ) + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD ) ; } </s>


<s> static void nds32_conditional_register_usage ( void ) { int regno ; if ( TARGET_LINUX_ABI ) fixed_regs [ TP_REGNUM ] = 1 ; if ( TARGET_HARD_FLOAT ) { for ( regno = NDS32_FIRST_FPR_REGNUM ; regno <= NDS32_LAST_FPR_REGNUM ; regno ++ ) { fixed_regs [ regno ] = 0 ; if ( regno < NDS32_FIRST_FPR_REGNUM + NDS32_MAX_FPR_REGS_FOR_ARGS ) call_used_regs [ regno ] = 1 ; else if ( regno >= NDS32_FIRST_FPR_REGNUM + 22 && regno < NDS32_FIRST_FPR_REGNUM + 48 ) call_used_regs [ regno ] = 1 ; else call_used_regs [ regno ] = 0 ; } } else if ( TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE ) { for ( regno = NDS32_FIRST_FPR_REGNUM ; regno <= NDS32_LAST_FPR_REGNUM ; regno ++ ) fixed_regs [ regno ] = 0 ; } } </s>


<s> static HOST_WIDE_INT nds32_constant_alignment ( const_tree constant , HOST_WIDE_INT basic_align ) { if ( ( ( TREE_CODE ( constant ) == STRING_CST || TREE_CODE ( constant ) == CONSTRUCTOR || TREE_CODE ( constant ) == UNION_TYPE || TREE_CODE ( constant ) == RECORD_TYPE || TREE_CODE ( constant ) == ARRAY_TYPE ) && basic_align < BITS_PER_WORD ) ) return BITS_PER_WORD ; else return basic_align ; } </s>


<s> void nds32_cpu_cpp_builtins ( struct cpp_reader * pfile ) { builtin_define ( "__nds32__" ) ; builtin_define ( "__NDS32__" ) ; if ( ! TARGET_LINUX_ABI ) { if ( TARGET_ISR_VECTOR_SIZE_4_BYTE ) builtin_define ( "__NDS32_ISR_VECTOR_SIZE_4__" ) ; else builtin_define ( "__NDS32_ISR_VECTOR_SIZE_16__" ) ; } if ( TARGET_HARD_FLOAT ) builtin_define ( "__NDS32_ABI_2FP_PLUS__" ) ; else builtin_define ( "__NDS32_ABI_2__" ) ; if ( TARGET_ISA_V2 ) builtin_define ( "__NDS32_ISA_V2__" ) ; if ( TARGET_ISA_V3 ) builtin_define ( "__NDS32_ISA_V3__" ) ; if ( TARGET_ISA_V3M ) builtin_define ( "__NDS32_ISA_V3M__" ) ; if ( TARGET_FPU_SINGLE ) builtin_define ( "__NDS32_EXT_FPU_SP__" ) ; if ( TARGET_FPU_DOUBLE ) builtin_define ( "__NDS32_EXT_FPU_DP__" ) ; if ( TARGET_EXT_FPU_FMA ) builtin_define ( "__NDS32_EXT_FPU_FMA__" ) ; if ( NDS32_EXT_FPU_DOT_E ) builtin_define ( "__NDS32_EXT_FPU_DOT_E__" ) ; if ( TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE ) { switch ( nds32_fp_regnum ) { case 0 : case 4 : builtin_define ( "__NDS32_EXT_FPU_CONFIG_0__" ) ; break ; case 1 : case 5 : builtin_define ( "__NDS32_EXT_FPU_CONFIG_1__" ) ; break ; case 2 : case 6 : builtin_define ( "__NDS32_EXT_FPU_CONFIG_2__" ) ; break ; case 3 : case 7 : builtin_define ( "__NDS32_EXT_FPU_CONFIG_3__" ) ; break ; default : abort ( ) ; } } if ( TARGET_BIG_ENDIAN ) builtin_define ( "__NDS32_EB__" ) ; else builtin_define ( "__NDS32_EL__" ) ; if ( TARGET_REDUCED_REGS ) builtin_define ( "__NDS32_REDUCED_REGS__" ) ; if ( TARGET_CMOV ) builtin_define ( "__NDS32_CMOV__" ) ; if ( TARGET_EXT_PERF ) builtin_define ( "__NDS32_EXT_PERF__" ) ; if ( TARGET_EXT_PERF2 ) builtin_define ( "__NDS32_EXT_PERF2__" ) ; if ( TARGET_EXT_STRING ) builtin_define ( "__NDS32_EXT_STRING__" ) ; if ( TARGET_16_BIT ) builtin_define ( "__NDS32_16_BIT__" ) ; if ( TARGET_GP_DIRECT ) builtin_define ( "__NDS32_GP_DIRECT__" ) ; if ( TARGET_VH ) builtin_define ( "__NDS32_VH__" ) ; if ( NDS32_EXT_DSP_P ( ) ) builtin_define ( "__NDS32_EXT_DSP__" ) ; if ( TARGET_BIG_ENDIAN ) builtin_define ( "__big_endian__" ) ; builtin_assert ( "cpu=nds32" ) ; builtin_assert ( "machine=nds32" ) ; if ( TARGET_HARD_FLOAT ) builtin_define ( "__NDS32_ABI_2FP_PLUS" ) ; else builtin_define ( "__NDS32_ABI_2" ) ; } </s>


<s> unsigned int nds32_data_alignment ( tree data , unsigned int basic_align ) { if ( ( basic_align < BITS_PER_WORD ) && ( TREE_CODE ( data ) == ARRAY_TYPE || TREE_CODE ( data ) == UNION_TYPE || TREE_CODE ( data ) == RECORD_TYPE ) ) return BITS_PER_WORD ; else return basic_align ; } </s>


<s> unsigned int nds32_dbx_register_number ( unsigned int regno ) { if ( NDS32_IS_FPR_REGNUM ( regno ) ) return regno + 4 ; return regno ; } </s>

Map internal gcc register numbers to DWARF2 register numbers .


<s> static rtx nds32_delegitimize_address ( rtx x ) { x = delegitimize_mem_from_attrs ( x ) ; if ( GET_CODE ( x ) == CONST ) { rtx inner = XEXP ( x , 0 ) ; if ( GET_CODE ( inner ) == PLUS ) inner = XEXP ( inner , 0 ) ; if ( GET_CODE ( inner ) == UNSPEC ) { switch ( XINT ( inner , 1 ) ) { case UNSPEC_GOTINIT : case UNSPEC_GOT : case UNSPEC_GOTOFF : case UNSPEC_PLT : case UNSPEC_TLSGD : case UNSPEC_TLSLD : case UNSPEC_TLSIE : case UNSPEC_TLSLE : case UNSPEC_ICT : x = XVECEXP ( inner , 0 , 0 ) ; break ; default : break ; } } } return x ; } </s>

Reorgnize the UNSPEC CONST and return its direct symbol .


Function that may creates more instructions for large value on adjusting stack pointer . In nds32 target , 'addi ' can be used for stack pointer adjustment in prologue/epilogue stage . However , sometimes there are too many local variables so that the adjustment value is not able to be fit in the 'addi ' instruction . One solution is to move value into a register and then use 'add ' instruction . In practice , we use TA_REGNUM ( $ r15 ) to accomplish this purpose .


<s> static void nds32_emit_stack_push_multiple ( unsigned Rb , unsigned Re , bool save_fp_p , bool save_gp_p , bool save_lp_p , bool vaarg_p ) { unsigned regno ; int extra_count ; int num_use_regs ; int par_index ; int offset ; rtx reg ; rtx mem ; rtx push_rtx ; rtx adjust_sp_rtx ; rtx parallel_insn ; rtx dwarf ; extra_count = 0 ; if ( save_fp_p ) extra_count ++ ; if ( save_gp_p ) extra_count ++ ; if ( save_lp_p ) extra_count ++ ; if ( Rb == SP_REGNUM && Re == SP_REGNUM ) num_use_regs = extra_count ; else num_use_regs = Re - Rb + 1 + extra_count ; parallel_insn = gen_rtx_PARALLEL ( VOIDmode , rtvec_alloc ( num_use_regs + 1 ) ) ; par_index = 0 ; offset = - ( num_use_regs * 4 ) ; for ( regno = Rb ; regno <= Re ; regno ++ ) { if ( regno == SP_REGNUM ) break ; reg = gen_rtx_REG ( SImode , regno ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; } if ( save_fp_p ) { reg = gen_rtx_REG ( SImode , FP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; } if ( save_gp_p ) { reg = gen_rtx_REG ( SImode , GP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; } if ( save_lp_p ) { reg = gen_rtx_REG ( SImode , LP_REGNUM ) ; mem = gen_frame_mem ( SImode , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; push_rtx = gen_rtx_SET ( mem , reg ) ; XVECEXP ( parallel_insn , 0 , par_index ) = push_rtx ; RTX_FRAME_RELATED_P ( push_rtx ) = 1 ; offset = offset + 4 ; par_index ++ ; } offset = - ( num_use_regs * 4 ) ; adjust_sp_rtx = gen_rtx_SET ( stack_pointer_rtx , plus_constant ( Pmode , stack_pointer_rtx , offset ) ) ; XVECEXP ( parallel_insn , 0 , par_index ) = adjust_sp_rtx ; RTX_FRAME_RELATED_P ( adjust_sp_rtx ) = 1 ; parallel_insn = emit_insn ( parallel_insn ) ; RTX_FRAME_RELATED_P ( parallel_insn ) = 1 ; if ( vaarg_p ) { dwarf = alloc_reg_note ( REG_CFA_ADJUST_CFA , copy_rtx ( adjust_sp_rtx ) , NULL_RTX ) ; REG_NOTES ( parallel_insn ) = dwarf ; } } </s>

Function to create a parallel rtx pattern which presents stack push multiple behavior . The overall concept are : `` push registers to memory '' , `` adjust stack pointer '' .